Coverage Report

Created: 2025-11-11 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ndpi/src/lib/ndpi_utils.c
Line
Count
Source
1
/*
2
 * ndpi_utils.c
3
 *
4
 * Copyright (C) 2011-25 - ntop.org and contributors
5
 *
6
 * nDPI 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
 * nDPI 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
 * along with nDPI.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 */
20
21
22
#include <stdlib.h>
23
#include <errno.h>
24
#include <math.h>
25
#include <sys/types.h>
26
27
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_UNKNOWN
28
29
#include "ndpi_config.h"
30
#include "ndpi_api.h"
31
#include "ndpi_includes.h"
32
#include "ndpi_encryption.h"
33
#include "ndpi_private.h"
34
35
#include "ahocorasick.h"
36
#include "libcache.h"
37
#include "shoco.h"
38
39
#include <time.h>
40
#ifndef WIN32
41
#include <unistd.h>
42
#endif
43
44
#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
45
#include <sys/endian.h>
46
#endif
47
48
#include "third_party/include/ndpi_patricia.h"
49
#include "third_party/include/libinjection.h"
50
#include "third_party/include/libinjection_sqli.h"
51
#include "third_party/include/libinjection_xss.h"
52
#include "third_party/include/uthash.h"
53
#include "third_party/include/rce_injection.h"
54
55
#include "ndpi_replace_printf.h"
56
#include "ndpi_sha256.h"
57
58
#define NDPI_CONST_GENERIC_PROTOCOL_NAME  "GenericProtocol"
59
60
// #define MATCH_DEBUG 1
61
62
// #define DEBUG_REASSEMBLY
63
64
#ifdef HAVE_PCRE2
65
#define PCRE2_CODE_UNIT_WIDTH 8
66
#include <pcre2.h>
67
68
struct pcre2_struct {
69
  pcre2_code *compiled;
70
};
71
#endif
72
73
typedef struct {
74
  char *key;
75
  u_int64_t value64;
76
  UT_hash_handle hh;
77
} ndpi_str_hash_priv;
78
79
/* ****************************************** */
80
81
/* implementation of the punycode check function */
82
266
int ndpi_check_punycode_string(char * buffer , int len) {
83
266
  int i = 0;
84
85
8.02k
  while(i < len - 3) {
86
7.76k
    if((buffer[i] == 'x')
87
22
       && (buffer[i+1] == 'n')
88
8
       && (buffer[i+2] == '-')
89
0
       && (buffer[i+3] == '-'))
90
      // is a punycode string
91
0
      return(1);
92
7.76k
    i++;
93
7.76k
  }
94
95
  // not a punycode string
96
266
  return 0;
97
266
}
98
99
/* ****************************************** */
100
101
/* ftp://ftp.cc.uoc.gr/mirrors/OpenBSD/src/lib/libc/stdlib/tsearch.c */
102
/* find or insert datum into search tree */
103
void * ndpi_tsearch(const void *vkey, void **vrootp,
104
        int (*compar)(const void *, const void *))
105
229k
{
106
229k
  ndpi_node *q;
107
229k
  char *key = (char *)vkey;
108
229k
  ndpi_node **rootp = (ndpi_node **)vrootp;
109
110
229k
  if(rootp == (ndpi_node **)0)
111
0
    return ((void *)0);
112
2.71M
  while (*rootp != (ndpi_node *)0) { /* Knuth's T1: */
113
2.48M
    int r;
114
115
2.48M
    if((r = (*compar)(key, (*rootp)->key)) == 0)  /* T2: */
116
1.63k
      return ((*rootp)->key);  /* we found it! */
117
2.48M
    rootp = (r < 0) ?
118
592k
      &(*rootp)->left :    /* T3: follow left branch */
119
2.48M
      &(*rootp)->right;   /* T4: follow right branch */
120
2.48M
  }
121
228k
  q = (ndpi_node *) ndpi_malloc(sizeof(ndpi_node)); /* T5: key not found */
122
228k
  if(q != (ndpi_node *)0) { /* make new node */
123
226k
    *rootp = q;     /* link new node to old */
124
226k
    q->key = key;   /* initialize new node */
125
226k
    q->left = q->right = (ndpi_node *)0;
126
226k
    return ((void *)q->key);
127
226k
  }
128
1.43k
  return ((void *)0);
129
228k
}
130
131
/* ****************************************** */
132
133
/* delete node with given key */
134
void * ndpi_tdelete(const void *vkey, void **vrootp,
135
        int (*compar)(const void *, const void *))
136
0
{
137
0
  ndpi_node **rootp = (ndpi_node **)vrootp;
138
0
  char *key = (char *)vkey;
139
0
  ndpi_node *q;
140
0
  ndpi_node *r;
141
0
  int cmp;
142
143
0
  if(rootp == (ndpi_node **)0 || *rootp == (ndpi_node *)0)
144
0
    return((void *)0);
145
0
  while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
146
0
    rootp = (cmp < 0) ?
147
0
      &(*rootp)->left :    /* follow left branch */
148
0
      &(*rootp)->right;   /* follow right branch */
149
0
    if(*rootp == (ndpi_node *)0)
150
0
      return ((void *)0);   /* key not found */
151
0
  }
152
0
  r = (*rootp)->right;      /* D1: */
153
0
  if((q = (*rootp)->left) == (ndpi_node *)0) /* Left (ndpi_node *)0? */
154
0
    q = r;
155
0
  else if(r != (ndpi_node *)0) {   /* Right link is null? */
156
0
    if(r->left == (ndpi_node *)0) { /* D2: Find successor */
157
0
      r->left = q;
158
0
      q = r;
159
0
    } else {     /* D3: Find (ndpi_node *)0 link */
160
0
      for(q = r->left; q->left != (ndpi_node *)0; q = r->left)
161
0
  r = q;
162
0
      r->left = q->right;
163
0
      q->left = (*rootp)->left;
164
0
      q->right = (*rootp)->right;
165
0
    }
166
0
  }
167
0
  key = (*rootp)->key;
168
0
  ndpi_free((ndpi_node *) *rootp);  /* D4: Free node */
169
0
  *rootp = q;       /* link parent to new node */
170
171
  /* Return the key to give the caller a chance to free custom data */
172
0
  return(key);
173
0
}
174
175
/* ****************************************** */
176
177
/* Walk the nodes of a tree */
178
static void ndpi_trecurse(ndpi_node *root, void (*action)(const void *, ndpi_VISIT, int, void*), int level, void *user_data)
179
0
{
180
0
  if(root->left == (ndpi_node *)0 && root->right == (ndpi_node *)0)
181
0
    (*action)(root, ndpi_leaf, level, user_data);
182
0
  else {
183
0
    (*action)(root, ndpi_preorder, level, user_data);
184
0
    if(root->left != (ndpi_node *)0)
185
0
      ndpi_trecurse(root->left, action, level + 1, user_data);
186
0
    (*action)(root, ndpi_postorder, level, user_data);
187
0
    if(root->right != (ndpi_node *)0)
188
0
      ndpi_trecurse(root->right, action, level + 1, user_data);
189
0
    (*action)(root, ndpi_endorder, level, user_data);
190
0
  }
191
0
}
192
193
/* ****************************************** */
194
195
/* Walk the nodes of a tree */
196
void ndpi_twalk(const void *vroot, void (*action)(const void *, ndpi_VISIT, int, void *), void *user_data)
197
0
{
198
0
  ndpi_node *root = (ndpi_node *)vroot;
199
200
0
  if(root != (ndpi_node *)0 && action != (void (*)(const void *, ndpi_VISIT, int, void*))0)
201
0
    ndpi_trecurse(root, action, 0, user_data);
202
0
}
203
204
/* ****************************************** */
205
206
/* find a node, or return 0 */
207
void * ndpi_tfind(const void *vkey, void *vrootp,
208
      int (*compar)(const void *, const void *))
209
2.28k
{
210
2.28k
  char *key = (char *)vkey;
211
2.28k
  ndpi_node **rootp = (ndpi_node **)vrootp;
212
213
2.28k
  if(rootp == (ndpi_node **)0)
214
0
    return ((ndpi_node *)0);
215
39.2k
  while (*rootp != (ndpi_node *)0) { /* T1: */
216
37.3k
    int r;
217
37.3k
    if((r = (*compar)(key, (*rootp)->key)) == 0)  /* T2: */
218
360
      return (*rootp);    /* key found */
219
36.9k
    rootp = (r < 0) ?
220
5.66k
      &(*rootp)->left :    /* T3: follow left branch */
221
36.9k
      &(*rootp)->right;   /* T4: follow right branch */
222
36.9k
  }
223
1.92k
  return (ndpi_node *)0;
224
2.28k
}
225
226
/* ****************************************** */
227
228
/* Walk the nodes of a tree */
229
static void ndpi_tdestroy_recurse(ndpi_node* root, void (*free_action)(void *))
230
226k
{
231
226k
  if(root->left != NULL)
232
91.0k
    ndpi_tdestroy_recurse(root->left, free_action);
233
226k
  if(root->right != NULL)
234
134k
    ndpi_tdestroy_recurse(root->right, free_action);
235
236
226k
  (*free_action) ((void *) root->key);
237
226k
  ndpi_free(root);
238
226k
}
239
240
void ndpi_tdestroy(void *vrootp, void (*freefct)(void *))
241
1.66k
{
242
1.66k
  ndpi_node *root = (ndpi_node *) vrootp;
243
244
1.66k
  if(root != NULL)
245
1.66k
    ndpi_tdestroy_recurse(root, freefct);
246
1.66k
}
247
248
/* ****************************************** */
249
250
u_int8_t ndpi_net_match(u_int32_t ip_to_check,
251
      u_int32_t net,
252
1.06k
      u_int32_t num_bits) {
253
1.06k
  u_int32_t mask = 0;
254
255
1.06k
  num_bits &= 0x1F; /* Avoid overflows */
256
257
1.06k
  mask = ~(~mask >> num_bits);
258
259
1.06k
  return(((ip_to_check & mask) == (net & mask)) ? 1 : 0);
260
1.06k
}
261
262
u_int8_t ndpi_ips_match(u_int32_t src, u_int32_t dst,
263
765
      u_int32_t net, u_int32_t num_bits) {
264
765
  return(ndpi_net_match(src, net, num_bits) || ndpi_net_match(dst, net, num_bits));
265
765
}
266
267
/* **************************************** */
268
269
2
u_int8_t ndpi_is_safe_ssl_cipher(u_int32_t cipher) {
270
  /* https://community.qualys.com/thread/18212-how-does-qualys-determine-the-server-cipher-suites */
271
272
2
  switch(cipher) {
273
    /* INSECURE */
274
0
  case TLS_ECDHE_RSA_WITH_RC4_128_SHA: return(NDPI_CIPHER_INSECURE);
275
0
  case TLS_RSA_WITH_RC4_128_SHA: return(NDPI_CIPHER_INSECURE);
276
0
  case TLS_RSA_WITH_RC4_128_MD5: return(NDPI_CIPHER_INSECURE);
277
278
    /* WEAK */
279
0
  case TLS_RSA_WITH_AES_256_GCM_SHA384: return(NDPI_CIPHER_WEAK);
280
0
  case TLS_RSA_WITH_AES_256_CBC_SHA256: return(NDPI_CIPHER_WEAK);
281
0
  case TLS_RSA_WITH_AES_256_CBC_SHA: return(NDPI_CIPHER_WEAK);
282
0
  case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: return(NDPI_CIPHER_WEAK);
283
0
  case TLS_RSA_WITH_AES_128_GCM_SHA256: return(NDPI_CIPHER_WEAK);
284
0
  case TLS_RSA_WITH_AES_128_CBC_SHA256: return(NDPI_CIPHER_WEAK);
285
0
  case TLS_RSA_WITH_AES_128_CBC_SHA: return(NDPI_CIPHER_WEAK);
286
0
  case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: return(NDPI_CIPHER_WEAK);
287
0
  case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: return(NDPI_CIPHER_WEAK);
288
0
  case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: return(NDPI_CIPHER_WEAK);
289
0
  case TLS_RSA_WITH_3DES_EDE_CBC_SHA: return(NDPI_CIPHER_WEAK);
290
0
  case TLS_RSA_WITH_SEED_CBC_SHA: return(NDPI_CIPHER_WEAK);
291
0
  case TLS_RSA_WITH_IDEA_CBC_SHA: return(NDPI_CIPHER_WEAK);
292
293
2
  default:
294
2
    return(NDPI_CIPHER_SAFE);
295
2
  }
296
2
}
297
298
/* ***************************************************** */
299
300
0
const char* ndpi_cipher2str(u_int32_t cipher, char unknown_cipher[8]) {
301
0
  switch(cipher) {
302
0
  case TLS_NULL_WITH_NULL_NULL: return("TLS_NULL_WITH_NULL_NULL");
303
0
  case TLS_RSA_EXPORT_WITH_RC4_40_MD5: return("TLS_RSA_EXPORT_WITH_RC4_40_MD5");
304
0
  case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5: return("TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5");
305
0
  case TLS_RSA_EXPORT_WITH_DES40_CBC_SHA: return("TLS_RSA_EXPORT_WITH_DES40_CBC_SHA");
306
0
  case TLS_RSA_WITH_NULL_MD5: return("TLS_RSA_WITH_NULL_MD5");
307
0
  case TLS_RSA_WITH_NULL_SHA: return("TLS_RSA_WITH_NULL_SHA");
308
0
  case TLS_RSA_WITH_NULL_SHA256: return("TLS_RSA_WITH_NULL_SHA256");
309
0
  case TLS_RSA_WITH_RC4_128_MD5: return("TLS_RSA_WITH_RC4_128_MD5");
310
0
  case TLS_RSA_WITH_RC4_128_SHA: return("TLS_RSA_WITH_RC4_128_SHA");
311
0
  case TLS_RSA_WITH_IDEA_CBC_SHA: return("TLS_RSA_WITH_IDEA_CBC_SHA");
312
0
  case TLS_RSA_WITH_DES_CBC_SHA: return("TLS_RSA_WITH_DES_CBC_SHA");
313
0
  case TLS_RSA_WITH_3DES_EDE_CBC_SHA: return("TLS_RSA_WITH_3DES_EDE_CBC_SHA");
314
0
  case TLS_RSA_WITH_AES_128_CBC_SHA: return("TLS_RSA_WITH_AES_128_CBC_SHA");
315
0
  case TLS_RSA_WITH_AES_256_CBC_SHA: return("TLS_RSA_WITH_AES_256_CBC_SHA");
316
0
  case TLS_RSA_WITH_AES_128_CBC_SHA256: return("TLS_RSA_WITH_AES_128_CBC_SHA256");
317
0
  case TLS_RSA_WITH_AES_256_CBC_SHA256: return("TLS_RSA_WITH_AES_256_CBC_SHA256");
318
0
  case TLS_RSA_WITH_AES_128_GCM_SHA256: return("TLS_RSA_WITH_AES_128_GCM_SHA256");
319
0
  case TLS_RSA_WITH_AES_256_GCM_SHA384: return("TLS_RSA_WITH_AES_256_GCM_SHA384");
320
0
  case TLS_RSA_WITH_AES_128_CCM: return("TLS_RSA_WITH_AES_128_CCM");
321
0
  case TLS_RSA_WITH_AES_256_CCM: return("TLS_RSA_WITH_AES_256_CCM");
322
0
  case TLS_RSA_WITH_AES_128_CCM_8: return("TLS_RSA_WITH_AES_128_CCM_8");
323
0
  case TLS_RSA_WITH_AES_256_CCM_8: return("TLS_RSA_WITH_AES_256_CCM_8");
324
0
  case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: return("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA");
325
0
  case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: return("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA");
326
0
  case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256");
327
0
  case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: return("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256");
328
0
  case TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256");
329
0
  case TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384");
330
0
  case TLS_RSA_WITH_SEED_CBC_SHA: return("TLS_RSA_WITH_SEED_CBC_SHA");
331
0
  case TLS_RSA_WITH_ARIA_128_CBC_SHA256: return("TLS_RSA_WITH_ARIA_128_CBC_SHA256");
332
0
  case TLS_RSA_WITH_ARIA_256_CBC_SHA384: return("TLS_RSA_WITH_ARIA_256_CBC_SHA384");
333
0
  case TLS_RSA_WITH_ARIA_128_GCM_SHA256: return("TLS_RSA_WITH_ARIA_128_GCM_SHA256");
334
0
  case TLS_RSA_WITH_ARIA_256_GCM_SHA384: return("TLS_RSA_WITH_ARIA_256_GCM_SHA384");
335
0
  case TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: return("TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA");
336
0
  case TLS_DH_RSA_WITH_DES_CBC_SHA: return("TLS_DH_RSA_WITH_DES_CBC_SHA");
337
0
  case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: return("TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA");
338
0
  case TLS_DH_RSA_WITH_AES_128_CBC_SHA: return("TLS_DH_RSA_WITH_AES_128_CBC_SHA");
339
0
  case TLS_DH_RSA_WITH_AES_256_CBC_SHA: return("TLS_DH_RSA_WITH_AES_256_CBC_SHA");
340
0
  case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: return("TLS_DH_RSA_WITH_AES_128_CBC_SHA256");
341
0
  case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: return("TLS_DH_RSA_WITH_AES_256_CBC_SHA256");
342
0
  case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: return("TLS_DH_RSA_WITH_AES_128_GCM_SHA256");
343
0
  case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: return("TLS_DH_RSA_WITH_AES_256_GCM_SHA384");
344
0
  case TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: return("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA");
345
0
  case TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: return("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA");
346
0
  case TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256");
347
0
  case TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: return("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256");
348
0
  case TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256");
349
0
  case TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384");
350
0
  case TLS_DH_RSA_WITH_SEED_CBC_SHA: return("TLS_DH_RSA_WITH_SEED_CBC_SHA");
351
0
  case TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256: return("TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256");
352
0
  case TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384: return("TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384");
353
0
  case TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256: return("TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256");
354
0
  case TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384: return("TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384");
355
0
  case TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: return("TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA");
356
0
  case TLS_DHE_RSA_WITH_DES_CBC_SHA: return("TLS_DHE_RSA_WITH_DES_CBC_SHA");
357
0
  case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: return("TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
358
0
  case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: return("TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
359
0
  case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: return("TLS_DHE_RSA_WITH_AES_256_CBC_SHA");
360
0
  case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: return("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256");
361
0
  case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: return("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256");
362
0
  case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: return("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256");
363
0
  case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: return("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384");
364
0
  case TLS_DHE_RSA_WITH_AES_128_CCM: return("TLS_DHE_RSA_WITH_AES_128_CCM");
365
0
  case TLS_DHE_RSA_WITH_AES_256_CCM: return("TLS_DHE_RSA_WITH_AES_256_CCM");
366
0
  case TLS_DHE_RSA_WITH_AES_128_CCM_8: return("TLS_DHE_RSA_WITH_AES_128_CCM_8");
367
0
  case TLS_DHE_RSA_WITH_AES_256_CCM_8: return("TLS_DHE_RSA_WITH_AES_256_CCM_8");
368
0
  case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: return("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA");
369
0
  case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: return("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA");
370
0
  case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256");
371
0
  case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: return("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256");
372
0
  case TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256");
373
0
  case TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384");
374
0
  case TLS_DHE_RSA_WITH_SEED_CBC_SHA: return("TLS_DHE_RSA_WITH_SEED_CBC_SHA");
375
0
  case TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256: return("TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256");
376
0
  case TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384: return("TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384");
377
0
  case TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256: return("TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256");
378
0
  case TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384: return("TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384");
379
0
  case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: return("TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256");
380
0
  case TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: return("TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA");
381
0
  case TLS_DH_DSS_WITH_DES_CBC_SHA: return("TLS_DH_DSS_WITH_DES_CBC_SHA");
382
0
  case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: return("TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA");
383
0
  case TLS_DH_DSS_WITH_AES_128_CBC_SHA: return("TLS_DH_DSS_WITH_AES_128_CBC_SHA");
384
0
  case TLS_DH_DSS_WITH_AES_256_CBC_SHA: return("TLS_DH_DSS_WITH_AES_256_CBC_SHA");
385
0
  case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: return("TLS_DH_DSS_WITH_AES_128_CBC_SHA256");
386
0
  case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: return("TLS_DH_DSS_WITH_AES_256_CBC_SHA256");
387
0
  case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: return("TLS_DH_DSS_WITH_AES_128_GCM_SHA256");
388
0
  case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: return("TLS_DH_DSS_WITH_AES_256_GCM_SHA384");
389
0
  case TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: return("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA");
390
0
  case TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: return("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA");
391
0
  case TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256");
392
0
  case TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: return("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256");
393
0
  case TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256");
394
0
  case TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384");
395
0
  case TLS_DH_DSS_WITH_SEED_CBC_SHA: return("TLS_DH_DSS_WITH_SEED_CBC_SHA");
396
0
  case TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256: return("TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256");
397
0
  case TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384: return("TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384");
398
0
  case TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256: return("TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256");
399
0
  case TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384: return("TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384");
400
0
  case TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: return("TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
401
0
  case TLS_DHE_DSS_WITH_DES_CBC_SHA: return("TLS_DHE_DSS_WITH_DES_CBC_SHA");
402
0
  case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: return("TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA");
403
0
  case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: return("TLS_DHE_DSS_WITH_AES_128_CBC_SHA");
404
0
  case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: return("TLS_DHE_DSS_WITH_AES_256_CBC_SHA");
405
0
  case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: return("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256");
406
0
  case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: return("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256");
407
0
  case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: return("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256");
408
0
  case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: return("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384");
409
0
  case TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: return("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA");
410
0
  case TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: return("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA");
411
0
  case TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256");
412
0
  case TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: return("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256");
413
0
  case TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256");
414
0
  case TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384");
415
0
  case TLS_DHE_DSS_WITH_SEED_CBC_SHA: return("TLS_DHE_DSS_WITH_SEED_CBC_SHA");
416
0
  case TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256: return("TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256");
417
0
  case TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384: return("TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384");
418
0
  case TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256: return("TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256");
419
0
  case TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384: return("TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384");
420
0
  case TLS_DH_ANON_EXPORT_WITH_RC4_40_MD5: return("TLS_DH_ANON_EXPORT_WITH_RC4_40_MD5");
421
0
  case TLS_DH_ANON_EXPORT_WITH_DES40_CBC_SHA: return("TLS_DH_ANON_EXPORT_WITH_DES40_CBC_SHA");
422
0
  case TLS_DH_ANON_WITH_RC4_128_MD5: return("TLS_DH_ANON_WITH_RC4_128_MD5");
423
0
  case TLS_DH_ANON_WITH_DES_CBC_SHA: return("TLS_DH_ANON_WITH_DES_CBC_SHA");
424
0
  case TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA: return("TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA");
425
0
  case TLS_DH_ANON_WITH_AES_128_CBC_SHA: return("TLS_DH_ANON_WITH_AES_128_CBC_SHA");
426
0
  case TLS_DH_ANON_WITH_AES_256_CBC_SHA: return("TLS_DH_ANON_WITH_AES_256_CBC_SHA");
427
0
  case TLS_DH_ANON_WITH_AES_128_CBC_SHA256: return("TLS_DH_ANON_WITH_AES_128_CBC_SHA256");
428
0
  case TLS_DH_ANON_WITH_AES_256_CBC_SHA256: return("TLS_DH_ANON_WITH_AES_256_CBC_SHA256");
429
0
  case TLS_DH_ANON_WITH_AES_128_GCM_SHA256: return("TLS_DH_ANON_WITH_AES_128_GCM_SHA256");
430
0
  case TLS_DH_ANON_WITH_AES_256_GCM_SHA384: return("TLS_DH_ANON_WITH_AES_256_GCM_SHA384");
431
0
  case TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA: return("TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA");
432
0
  case TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA: return("TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA");
433
0
  case TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA256");
434
0
  case TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA256: return("TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA256");
435
0
  case TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256");
436
0
  case TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384");
437
0
  case TLS_DH_ANON_WITH_SEED_CBC_SHA: return("TLS_DH_ANON_WITH_SEED_CBC_SHA");
438
0
  case TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256: return("TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256");
439
0
  case TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384: return("TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384");
440
0
  case TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256: return("TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256");
441
0
  case TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384: return("TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384");
442
0
  case TLS_ECDH_RSA_WITH_NULL_SHA: return("TLS_ECDH_RSA_WITH_NULL_SHA");
443
0
  case TLS_ECDH_RSA_WITH_RC4_128_SHA: return("TLS_ECDH_RSA_WITH_RC4_128_SHA");
444
0
  case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: return("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA");
445
0
  case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: return("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA");
446
0
  case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: return("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA");
447
0
  case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: return("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256");
448
0
  case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: return("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384");
449
0
  case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: return("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256");
450
0
  case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: return("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384");
451
0
  case TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256");
452
0
  case TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: return("TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384");
453
0
  case TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256");
454
0
  case TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384");
455
0
  case TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256: return("TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256");
456
0
  case TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384: return("TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384");
457
0
  case TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256: return("TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256");
458
0
  case TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384: return("TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384");
459
0
  case TLS_ECDHE_RSA_WITH_NULL_SHA: return("TLS_ECDHE_RSA_WITH_NULL_SHA");
460
0
  case TLS_ECDHE_RSA_WITH_RC4_128_SHA: return("TLS_ECDHE_RSA_WITH_RC4_128_SHA");
461
0
  case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: return("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA");
462
0
  case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: return("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
463
0
  case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: return("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA");
464
0
  case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: return("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256");
465
0
  case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: return("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384");
466
0
  case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: return("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
467
0
  case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: return("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384");
468
0
  case TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256");
469
0
  case TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: return("TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384");
470
0
  case TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256");
471
0
  case TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384");
472
0
  case TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256: return("TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256");
473
0
  case TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384: return("TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384");
474
0
  case TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256: return("TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256");
475
0
  case TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384: return("TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384");
476
0
  case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: return("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256");
477
0
  case TLS_ECDH_ECDSA_WITH_NULL_SHA: return("TLS_ECDH_ECDSA_WITH_NULL_SHA");
478
0
  case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: return("TLS_ECDH_ECDSA_WITH_RC4_128_SHA");
479
0
  case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: return("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA");
480
0
  case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: return("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA");
481
0
  case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: return("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
482
0
  case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: return("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256");
483
0
  case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: return("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384");
484
0
  case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: return("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256");
485
0
  case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: return("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384");
486
0
  case TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256");
487
0
  case TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: return("TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384");
488
0
  case TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256");
489
0
  case TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384");
490
0
  case TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256: return("TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256");
491
0
  case TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384: return("TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384");
492
0
  case TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256: return("TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256");
493
0
  case TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384: return("TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384");
494
0
  case TLS_ECDHE_ECDSA_WITH_NULL_SHA: return("TLS_ECDHE_ECDSA_WITH_NULL_SHA");
495
0
  case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: return("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA");
496
0
  case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: return("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA");
497
0
  case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: return("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA");
498
0
  case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: return("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA");
499
0
  case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: return("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256");
500
0
  case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: return("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384");
501
0
  case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: return("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
502
0
  case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: return("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
503
0
  case TLS_ECDHE_ECDSA_WITH_AES_128_CCM: return("TLS_ECDHE_ECDSA_WITH_AES_128_CCM");
504
0
  case TLS_ECDHE_ECDSA_WITH_AES_256_CCM: return("TLS_ECDHE_ECDSA_WITH_AES_256_CCM");
505
0
  case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: return("TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8");
506
0
  case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: return("TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8");
507
0
  case TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256");
508
0
  case TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: return("TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384");
509
0
  case TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256");
510
0
  case TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384");
511
0
  case TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256: return("TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256");
512
0
  case TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384: return("TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384");
513
0
  case TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256: return("TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256");
514
0
  case TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384: return("TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384");
515
0
  case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: return("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256");
516
0
  case TLS_ECDH_ANON_WITH_NULL_SHA: return("TLS_ECDH_ANON_WITH_NULL_SHA");
517
0
  case TLS_ECDH_ANON_WITH_RC4_128_SHA: return("TLS_ECDH_ANON_WITH_RC4_128_SHA");
518
0
  case TLS_ECDH_ANON_WITH_3DES_EDE_CBC_SHA: return("TLS_ECDH_ANON_WITH_3DES_EDE_CBC_SHA");
519
0
  case TLS_ECDH_ANON_WITH_AES_128_CBC_SHA: return("TLS_ECDH_ANON_WITH_AES_128_CBC_SHA");
520
0
  case TLS_ECDH_ANON_WITH_AES_256_CBC_SHA: return("TLS_ECDH_ANON_WITH_AES_256_CBC_SHA");
521
0
  case TLS_PSK_WITH_NULL_SHA: return("TLS_PSK_WITH_NULL_SHA");
522
0
  case TLS_PSK_WITH_NULL_SHA256: return("TLS_PSK_WITH_NULL_SHA256");
523
0
  case TLS_PSK_WITH_NULL_SHA384: return("TLS_PSK_WITH_NULL_SHA384");
524
0
  case TLS_PSK_WITH_RC4_128_SHA: return("TLS_PSK_WITH_RC4_128_SHA");
525
0
  case TLS_PSK_WITH_3DES_EDE_CBC_SHA: return("TLS_PSK_WITH_3DES_EDE_CBC_SHA");
526
0
  case TLS_PSK_WITH_AES_128_CBC_SHA: return("TLS_PSK_WITH_AES_128_CBC_SHA");
527
0
  case TLS_PSK_WITH_AES_256_CBC_SHA: return("TLS_PSK_WITH_AES_256_CBC_SHA");
528
0
  case TLS_PSK_WITH_AES_128_CBC_SHA256: return("TLS_PSK_WITH_AES_128_CBC_SHA256");
529
0
  case TLS_PSK_WITH_AES_256_CBC_SHA384: return("TLS_PSK_WITH_AES_256_CBC_SHA384");
530
0
  case TLS_PSK_WITH_AES_128_GCM_SHA256: return("TLS_PSK_WITH_AES_128_GCM_SHA256");
531
0
  case TLS_PSK_WITH_AES_256_GCM_SHA384: return("TLS_PSK_WITH_AES_256_GCM_SHA384");
532
0
  case TLS_PSK_WITH_AES_128_CCM: return("TLS_PSK_WITH_AES_128_CCM");
533
0
  case TLS_PSK_WITH_AES_256_CCM: return("TLS_PSK_WITH_AES_256_CCM");
534
0
  case TLS_PSK_WITH_AES_128_CCM_8: return("TLS_PSK_WITH_AES_128_CCM_8");
535
0
  case TLS_PSK_WITH_AES_256_CCM_8: return("TLS_PSK_WITH_AES_256_CCM_8");
536
0
  case TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256");
537
0
  case TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: return("TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384");
538
0
  case TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256");
539
0
  case TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384");
540
0
  case TLS_PSK_WITH_ARIA_128_CBC_SHA256: return("TLS_PSK_WITH_ARIA_128_CBC_SHA256");
541
0
  case TLS_PSK_WITH_ARIA_256_CBC_SHA384: return("TLS_PSK_WITH_ARIA_256_CBC_SHA384");
542
0
  case TLS_PSK_WITH_ARIA_128_GCM_SHA256: return("TLS_PSK_WITH_ARIA_128_GCM_SHA256");
543
0
  case TLS_PSK_WITH_ARIA_256_GCM_SHA384: return("TLS_PSK_WITH_ARIA_256_GCM_SHA384");
544
0
  case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256: return("TLS_PSK_WITH_CHACHA20_POLY1305_SHA256");
545
0
  case TLS_RSA_PSK_WITH_NULL_SHA: return("TLS_RSA_PSK_WITH_NULL_SHA");
546
0
  case TLS_RSA_PSK_WITH_NULL_SHA256: return("TLS_RSA_PSK_WITH_NULL_SHA256");
547
0
  case TLS_RSA_PSK_WITH_NULL_SHA384: return("TLS_RSA_PSK_WITH_NULL_SHA384");
548
0
  case TLS_RSA_PSK_WITH_RC4_128_SHA: return("TLS_RSA_PSK_WITH_RC4_128_SHA");
549
0
  case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: return("TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA");
550
0
  case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: return("TLS_RSA_PSK_WITH_AES_128_CBC_SHA");
551
0
  case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: return("TLS_RSA_PSK_WITH_AES_256_CBC_SHA");
552
0
  case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: return("TLS_RSA_PSK_WITH_AES_128_CBC_SHA256");
553
0
  case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: return("TLS_RSA_PSK_WITH_AES_256_CBC_SHA384");
554
0
  case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: return("TLS_RSA_PSK_WITH_AES_128_GCM_SHA256");
555
0
  case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: return("TLS_RSA_PSK_WITH_AES_256_GCM_SHA384");
556
0
  case TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256");
557
0
  case TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: return("TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384");
558
0
  case TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256");
559
0
  case TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384");
560
0
  case TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256: return("TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256");
561
0
  case TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384: return("TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384");
562
0
  case TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256: return("TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256");
563
0
  case TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384: return("TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384");
564
0
  case TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256: return("TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256");
565
0
  case TLS_DHE_PSK_WITH_NULL_SHA: return("TLS_DHE_PSK_WITH_NULL_SHA");
566
0
  case TLS_DHE_PSK_WITH_NULL_SHA256: return("TLS_DHE_PSK_WITH_NULL_SHA256");
567
0
  case TLS_DHE_PSK_WITH_NULL_SHA384: return("TLS_DHE_PSK_WITH_NULL_SHA384");
568
0
  case TLS_DHE_PSK_WITH_RC4_128_SHA: return("TLS_DHE_PSK_WITH_RC4_128_SHA");
569
0
  case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: return("TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA");
570
0
  case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: return("TLS_DHE_PSK_WITH_AES_128_CBC_SHA");
571
0
  case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: return("TLS_DHE_PSK_WITH_AES_256_CBC_SHA");
572
0
  case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: return("TLS_DHE_PSK_WITH_AES_128_CBC_SHA256");
573
0
  case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: return("TLS_DHE_PSK_WITH_AES_256_CBC_SHA384");
574
0
  case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: return("TLS_DHE_PSK_WITH_AES_128_GCM_SHA256");
575
0
  case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: return("TLS_DHE_PSK_WITH_AES_256_GCM_SHA384");
576
0
  case TLS_DHE_PSK_WITH_AES_128_CCM: return("TLS_DHE_PSK_WITH_AES_128_CCM");
577
0
  case TLS_DHE_PSK_WITH_AES_256_CCM: return("TLS_DHE_PSK_WITH_AES_256_CCM");
578
0
  case TLS_DHE_PSK_WITH_AES_128_CCM_8: return("TLS_DHE_PSK_WITH_AES_128_CCM_8");
579
0
  case TLS_DHE_PSK_WITH_AES_256_CCM_8: return("TLS_DHE_PSK_WITH_AES_256_CCM_8");
580
0
  case TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256");
581
0
  case TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: return("TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384");
582
0
  case TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: return("TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256");
583
0
  case TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: return("TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384");
584
0
  case TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256: return("TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256");
585
0
  case TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384: return("TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384");
586
0
  case TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256: return("TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256");
587
0
  case TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384: return("TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384");
588
0
  case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256: return("TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256");
589
0
  case TLS_ECDHE_PSK_WITH_NULL_SHA: return("TLS_ECDHE_PSK_WITH_NULL_SHA");
590
0
  case TLS_ECDHE_PSK_WITH_NULL_SHA256: return("TLS_ECDHE_PSK_WITH_NULL_SHA256");
591
0
  case TLS_ECDHE_PSK_WITH_NULL_SHA384: return("TLS_ECDHE_PSK_WITH_NULL_SHA384");
592
0
  case TLS_ECDHE_PSK_WITH_RC4_128_SHA: return("TLS_ECDHE_PSK_WITH_RC4_128_SHA");
593
0
  case TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: return("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA");
594
0
  case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: return("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA");
595
0
  case TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: return("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA");
596
0
  case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: return("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256");
597
0
  case TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: return("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384");
598
0
  case TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256: return("TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256");
599
0
  case TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384: return("TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384");
600
0
  case TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256: return("TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256");
601
0
  case TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256: return("TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256");
602
0
  case TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: return("TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256");
603
0
  case TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: return("TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384");
604
0
  case TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256: return("TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256");
605
0
  case TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384: return("TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384");
606
0
  case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: return("TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256");
607
0
  case TLS_KRB5_EXPORT_WITH_RC4_40_MD5: return("TLS_KRB5_EXPORT_WITH_RC4_40_MD5");
608
0
  case TLS_KRB5_EXPORT_WITH_RC4_40_SHA: return("TLS_KRB5_EXPORT_WITH_RC4_40_SHA");
609
0
  case TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5: return("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5");
610
0
  case TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA: return("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA");
611
0
  case TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5: return("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5");
612
0
  case TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA: return("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA");
613
0
  case TLS_KRB5_WITH_RC4_128_MD5: return("TLS_KRB5_WITH_RC4_128_MD5");
614
0
  case TLS_KRB5_WITH_RC4_128_SHA: return("TLS_KRB5_WITH_RC4_128_SHA");
615
0
  case TLS_KRB5_WITH_IDEA_CBC_MD5: return("TLS_KRB5_WITH_IDEA_CBC_MD5");
616
0
  case TLS_KRB5_WITH_IDEA_CBC_SHA: return("TLS_KRB5_WITH_IDEA_CBC_SHA");
617
0
  case TLS_KRB5_WITH_DES_CBC_MD5: return("TLS_KRB5_WITH_DES_CBC_MD5");
618
0
  case TLS_KRB5_WITH_DES_CBC_SHA: return("TLS_KRB5_WITH_DES_CBC_SHA");
619
0
  case TLS_KRB5_WITH_3DES_EDE_CBC_MD5: return("TLS_KRB5_WITH_3DES_EDE_CBC_MD5");
620
0
  case TLS_KRB5_WITH_3DES_EDE_CBC_SHA: return("TLS_KRB5_WITH_3DES_EDE_CBC_SHA");
621
0
  case TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: return("TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA");
622
0
  case TLS_SRP_SHA_WITH_AES_128_CBC_SHA: return("TLS_SRP_SHA_WITH_AES_128_CBC_SHA");
623
0
  case TLS_SRP_SHA_WITH_AES_256_CBC_SHA: return("TLS_SRP_SHA_WITH_AES_256_CBC_SHA");
624
0
  case TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: return("TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA");
625
0
  case TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: return("TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA");
626
0
  case TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: return("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA");
627
0
  case TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: return("TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA");
628
0
  case TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: return("TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA");
629
0
  case TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: return("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA");
630
0
  case TLS_ECCPWD_WITH_AES_128_GCM_SHA256: return("TLS_ECCPWD_WITH_AES_128_GCM_SHA256");
631
0
  case TLS_ECCPWD_WITH_AES_256_GCM_SHA384: return("TLS_ECCPWD_WITH_AES_256_GCM_SHA384");
632
0
  case TLS_ECCPWD_WITH_AES_128_CCM_SHA256: return("TLS_ECCPWD_WITH_AES_128_CCM_SHA256");
633
0
  case TLS_ECCPWD_WITH_AES_256_CCM_SHA384: return("TLS_ECCPWD_WITH_AES_256_CCM_SHA384");
634
0
  case TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC: return("TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC");
635
0
  case TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC: return("TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC");
636
0
  case TLS_GOSTR341112_256_WITH_28147_CNT_IMIT: return("TLS_GOSTR341112_256_WITH_28147_CNT_IMIT");
637
0
  case TLS_AES_128_GCM_SHA256: return("TLS_AES_128_GCM_SHA256");
638
0
  case TLS_AES_256_GCM_SHA384: return("TLS_AES_256_GCM_SHA384");
639
0
  case TLS_AES_128_CCM_SHA256: return("TLS_AES_128_CCM_SHA256");
640
0
  case TLS_AES_128_CCM_8_SHA256: return("TLS_AES_128_CCM_8_SHA256");
641
0
  case TLS_CHACHA20_POLY1305_SHA256: return("TLS_CHACHA20_POLY1305_SHA256");
642
0
  case TLS_SM4_GCM_SM3: return("TLS_SM4_GCM_SM3");
643
0
  case TLS_SM4_CCM_SM3: return("TLS_SM4_CCM_SM3");
644
0
  case TLS_SHA256_SHA256: return("TLS_SHA256_SHA256");
645
0
  case TLS_SHA384_SHA384: return("TLS_SHA384_SHA384");
646
0
  case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: return("TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
647
0
  case TLS_FALLBACK_SCSV: return("TLS_FALLBACK_SCSV");
648
0
  case TLS_CIPHER_GREASE_RESERVED_0: return("TLS_CIPHER_GREASE_RESERVED_0");
649
0
  case TLS_CIPHER_GREASE_RESERVED_1: return("TLS_CIPHER_GREASE_RESERVED_1");
650
0
  case TLS_CIPHER_GREASE_RESERVED_2: return("TLS_CIPHER_GREASE_RESERVED_2");
651
0
  case TLS_CIPHER_GREASE_RESERVED_3: return("TLS_CIPHER_GREASE_RESERVED_3");
652
0
  case TLS_CIPHER_GREASE_RESERVED_4: return("TLS_CIPHER_GREASE_RESERVED_4");
653
0
  case TLS_CIPHER_GREASE_RESERVED_5: return("TLS_CIPHER_GREASE_RESERVED_5");
654
0
  case TLS_CIPHER_GREASE_RESERVED_6: return("TLS_CIPHER_GREASE_RESERVED_6");
655
0
  case TLS_CIPHER_GREASE_RESERVED_7: return("TLS_CIPHER_GREASE_RESERVED_7");
656
0
  case TLS_CIPHER_GREASE_RESERVED_8: return("TLS_CIPHER_GREASE_RESERVED_8");
657
0
  case TLS_CIPHER_GREASE_RESERVED_9: return("TLS_CIPHER_GREASE_RESERVED_9");
658
0
  case TLS_CIPHER_GREASE_RESERVED_A: return("TLS_CIPHER_GREASE_RESERVED_A");
659
0
  case TLS_CIPHER_GREASE_RESERVED_B: return("TLS_CIPHER_GREASE_RESERVED_B");
660
0
  case TLS_CIPHER_GREASE_RESERVED_C: return("TLS_CIPHER_GREASE_RESERVED_C");
661
0
  case TLS_CIPHER_GREASE_RESERVED_D: return("TLS_CIPHER_GREASE_RESERVED_D");
662
0
  case TLS_CIPHER_GREASE_RESERVED_E: return("TLS_CIPHER_GREASE_RESERVED_E");
663
0
  case TLS_CIPHER_GREASE_RESERVED_F: return("TLS_CIPHER_GREASE_RESERVED_F");
664
665
0
  default:
666
0
    {
667
0
      ndpi_snprintf(unknown_cipher, 8, "0X%04X", cipher);
668
0
      return(unknown_cipher);
669
0
    }
670
0
  }
671
0
}
672
673
/* ******************************************************************** */
674
675
0
static inline int ndpi_is_other_char(char c) {
676
0
  return((c == '.')
677
0
   || (c == ' ')
678
0
   || (c == '@')
679
0
   || (c == '/')
680
0
   );
681
0
}
682
683
/* ******************************************************************** */
684
685
0
static int _ndpi_is_valid_char(char c) {
686
0
  if(ndpi_ispunct(c) && (!ndpi_is_other_char(c)))
687
0
    return(0);
688
0
  else
689
0
    return(ndpi_isdigit(c)
690
0
     || ndpi_isalpha(c)
691
0
     || ndpi_is_other_char(c));
692
0
}
693
static char ndpi_is_valid_char_tbl[256],ndpi_is_valid_char_tbl_init=0;
694
695
0
static void _ndpi_is_valid_char_init(void) {
696
0
  int c;
697
0
  for(c=0; c < 256; c++) ndpi_is_valid_char_tbl[c] = _ndpi_is_valid_char(c);
698
0
  ndpi_is_valid_char_tbl_init = 1;
699
0
}
700
0
static inline int ndpi_is_valid_char(char c) {
701
0
  if(!ndpi_is_valid_char_tbl_init)
702
0
    _ndpi_is_valid_char_init();
703
0
  return ndpi_is_valid_char_tbl[(unsigned char)c];
704
0
}
705
706
/* ******************************************************************** */
707
708
0
static int ndpi_find_non_eng_bigrams(char *str) {
709
0
  char s[3];
710
711
0
  if((ndpi_isdigit(str[0]) && ndpi_isdigit(str[1]))
712
0
     || ndpi_is_other_char(str[0])
713
0
     || ndpi_is_other_char(str[1])
714
0
     )
715
0
    return(1);
716
717
0
  s[0] = tolower(str[0]), s[1] = tolower(str[1]), s[2] = '\0';
718
719
0
  return(ndpi_match_bigram(s));
720
0
}
721
722
/* ******************************************************************** */
723
724
/* #define PRINT_STRINGS 1 */
725
726
int ndpi_has_human_readable_string(char *buffer, u_int buffer_size,
727
            u_int8_t min_string_match_len,
728
0
            char *outbuf, u_int outbuf_len) {
729
0
  u_int ret = 0, i, do_cr = 0, len = 0, o_idx = 0, being_o_idx = 0;
730
731
0
  if(buffer_size <= 0)
732
0
    return(0);
733
734
0
  outbuf_len--;
735
0
  outbuf[outbuf_len] = '\0';
736
737
0
  for(i=0; i<buffer_size-2; i++) {
738
0
    if(ndpi_is_valid_char(buffer[i])
739
0
       && ndpi_is_valid_char(buffer[i+1])
740
0
       && ndpi_find_non_eng_bigrams(&buffer[i])) {
741
#ifdef PRINT_STRINGS
742
      printf("%c%c", buffer[i], buffer[i+1]);
743
#endif
744
0
      if(o_idx < outbuf_len) outbuf[o_idx++] = buffer[i];
745
0
      if(o_idx < outbuf_len) outbuf[o_idx++] = buffer[i+1];
746
0
      do_cr = 1, i += 1, len += 2;
747
0
    } else {
748
0
      if(ndpi_is_valid_char(buffer[i]) && do_cr) {
749
#ifdef PRINT_STRINGS
750
  printf("%c", buffer[i]);
751
#endif
752
0
  if(o_idx < outbuf_len) outbuf[o_idx++] = buffer[i];
753
0
  len += 1;
754
0
      }
755
756
      // printf("->> %c%c\n", ndpi_isprint(buffer[i]) ? buffer[i] : '.', ndpi_isprint(buffer[i+1]) ? buffer[i+1] : '.');
757
0
      if(do_cr) {
758
0
  if(len > min_string_match_len)
759
0
    ret = 1;
760
0
  else {
761
0
    o_idx = being_o_idx;
762
0
    being_o_idx = o_idx;
763
0
    outbuf[o_idx] = '\0';
764
0
  }
765
766
#ifdef PRINT_STRINGS
767
  printf(" [len: %u]%s\n", len, ret ? "<-- HIT" : "");
768
#endif
769
770
0
  if(ret)
771
0
    break;
772
773
0
  do_cr = 0, len = 0;
774
0
      }
775
0
    }
776
0
  }
777
778
#ifdef PRINT_STRINGS
779
  printf("=======>> Found string: %u\n", ret);
780
#endif
781
782
0
  return(ret);
783
0
}
784
785
/* ********************************** */
786
787
static const char* ndpi_get_flow_info_by_proto_id(struct ndpi_flow_struct const * const flow,
788
0
                                                  u_int16_t proto_id) {
789
0
  switch (proto_id) {
790
0
    case NDPI_PROTOCOL_WHOIS_DAS:
791
0
    case NDPI_PROTOCOL_MAIL_SMTP:
792
0
    case NDPI_PROTOCOL_NETBIOS:
793
0
    case NDPI_PROTOCOL_SSDP:
794
0
    case NDPI_PROTOCOL_MDNS:
795
0
    case NDPI_PROTOCOL_STUN:
796
0
    case NDPI_PROTOCOL_DNS:
797
0
    case NDPI_PROTOCOL_DHCP:
798
0
    case NDPI_PROTOCOL_XIAOMI:
799
0
    case NDPI_PROTOCOL_SD_RTN:
800
0
    case NDPI_PROTOCOL_COLLECTD:
801
0
    case NDPI_PROTOCOL_HTTP:
802
0
    case NDPI_PROTOCOL_HTTP_CONNECT:
803
0
    case NDPI_PROTOCOL_HTTP_PROXY:
804
0
      return flow->host_server_name;
805
806
0
    case NDPI_PROTOCOL_QUIC:
807
0
    case NDPI_PROTOCOL_TLS:
808
0
      if(flow->protos.tls_quic.client_hello_processed != 0)
809
0
        return flow->host_server_name;
810
0
      break;
811
0
  }
812
813
0
  return NULL;
814
0
}
815
816
/* ********************************** */
817
818
const char* ndpi_get_flow_info(struct ndpi_flow_struct const * const flow,
819
0
                               ndpi_protocol const * const l7_protocol) {
820
0
  char const * const app_protocol_info = ndpi_get_flow_info_by_proto_id(flow, l7_protocol->proto.app_protocol);
821
822
0
  if(app_protocol_info != NULL)
823
0
    return app_protocol_info;
824
825
0
  return ndpi_get_flow_info_by_proto_id(flow, l7_protocol->proto.master_protocol);
826
0
}
827
828
/* ********************************** */
829
830
char *ndpi_multimedia_flowtype2str(char *buf, int buf_len, u_int8_t m_types)
831
277
{
832
277
  int rc, len = 0;
833
834
277
  if(buf == NULL || buf_len <= 1)
835
113
    return NULL;
836
837
164
  buf[0] = '\0';
838
839
164
  if(m_types == ndpi_multimedia_unknown_flow) {
840
24
    rc = ndpi_snprintf(buf + len, buf_len - len, "Unknown", len > 0 ? ", " : "");
841
24
    if(rc > 0 && len + rc < buf_len) len += rc; else return NULL;
842
24
  }
843
844
164
  if(m_types & ndpi_multimedia_audio_flow) {
845
119
    rc = ndpi_snprintf(buf + len, buf_len - len, "%sAudio", len > 0 ? ", " : "");
846
119
    if(rc > 0 && len + rc < buf_len) len += rc; else return NULL;
847
119
  }
848
164
  if(m_types & ndpi_multimedia_video_flow) {
849
93
    rc = ndpi_snprintf(buf + len, buf_len - len, "%sVideo", len > 0 ? ", " : "");
850
93
    if(rc > 0 && len + rc < buf_len) len += rc; else return NULL;
851
93
  }
852
79
  if(m_types & ndpi_multimedia_screen_sharing_flow) {
853
21
    rc = ndpi_snprintf(buf + len, buf_len - len, "%sScreen Sharing", len > 0 ? ", " : "");
854
21
    if(rc > 0 && len + rc < buf_len) len += rc; else return NULL;
855
21
  }
856
857
58
  return buf;
858
79
}
859
860
/* ********************************** */
861
862
char* ndpi_ssl_version2str(char *buf, int buf_len,
863
766
                           u_int16_t version, u_int8_t *unknown_tls_version) {
864
766
  if(unknown_tls_version)
865
766
    *unknown_tls_version = 0;
866
867
766
  if(buf == NULL || buf_len <= 1)
868
488
    return NULL;
869
870
278
  switch(version) {
871
2
  case 0x0300: strncpy(buf, "SSLv3", buf_len); buf[buf_len - 1] = '\0'; return buf;
872
0
  case 0x0301: strncpy(buf, "TLSv1", buf_len); buf[buf_len - 1] = '\0'; return buf;
873
0
  case 0x0302: strncpy(buf, "TLSv1.1", buf_len); buf[buf_len - 1] = '\0'; return buf;
874
1
  case 0x0303: strncpy(buf, "TLSv1.2", buf_len); buf[buf_len - 1] = '\0'; return buf;
875
0
  case 0x0304: strncpy(buf, "TLSv1.3", buf_len); buf[buf_len - 1] = '\0'; return buf;
876
0
  case 0XFB1A: strncpy(buf, "TLSv1.3 (Fizz)", buf_len); buf[buf_len - 1] = '\0'; return buf; /* https://engineering.fb.com/security/fizz/ */
877
0
  case 0XFEFF: strncpy(buf, "DTLSv1.0", buf_len); buf[buf_len - 1] = '\0'; return buf;
878
0
  case 0XFEFD: strncpy(buf, "DTLSv1.2", buf_len); buf[buf_len - 1] = '\0'; return buf;
879
1
  case 0XFEFC: strncpy(buf, "DTLSv1.3", buf_len); buf[buf_len - 1] = '\0'; return buf;
880
0
  case 0x0A0A:
881
1
  case 0x1A1A:
882
1
  case 0x2A2A:
883
1
  case 0x3A3A:
884
1
  case 0x4A4A:
885
1
  case 0x5A5A:
886
1
  case 0x6A6A:
887
1
  case 0x7A7A:
888
2
  case 0x8A8A:
889
2
  case 0x9A9A:
890
2
  case 0xAAAA:
891
2
  case 0xBABA:
892
2
  case 0xCACA:
893
2
  case 0xDADA:
894
2
  case 0xEAEA:
895
2
  case 0xFAFA: strncpy(buf, "GREASE", buf_len);  buf[buf_len - 1] = '\0'; return buf;
896
278
  }
897
898
272
  if((version >= 0x7f00) && (version <= 0x7fff)) {
899
1
    strncpy(buf, "TLSv1.3 (draft)", buf_len);
900
1
    buf[buf_len - 1] = '\0';
901
1
    return buf;
902
1
  }
903
904
271
  if(unknown_tls_version)
905
271
    *unknown_tls_version = 1;
906
907
271
  ndpi_snprintf(buf, buf_len, "TLS (%04X)", version);
908
909
271
  return buf;
910
272
}
911
912
/* ***************************************************** */
913
914
0
void ndpi_patchIPv6Address(char *str) {
915
0
  int i = 0, j = 0;
916
917
0
  if (strstr(str, "::"))
918
0
   return;
919
920
0
  while(str[i] != '\0') {
921
0
    if((str[i] == ':')
922
0
       && (str[i+1] == '0')
923
0
       && (str[i+2] == ':')) {
924
0
      str[j++] = ':';
925
0
      str[j++] = ':';
926
0
      i += 3;
927
0
    } else
928
0
      str[j++] = str[i++];
929
0
  }
930
931
0
  if(str[j] != '\0') str[j] = '\0';
932
0
}
933
934
/* ********************************** */
935
936
void ndpi_user_pwd_payload_copy(u_int8_t *dest, u_int dest_len,
937
        u_int offset,
938
359
        const u_int8_t *src, u_int src_len) {
939
359
  u_int i, j=0, k = dest_len-1;
940
941
3.17k
  for(i=offset; (i<src_len) && (j<=k); i++) {
942
3.15k
    if((j == k) || (src[i] < ' '))
943
343
      break;
944
945
2.81k
    dest[j++] = src[i];
946
2.81k
  }
947
948
359
  dest[j <=k ? j : k] = '\0';
949
359
}
950
951
/* ********************************** */
952
/* ********************************** */
953
954
/* http://web.mit.edu/freebsd/head/contrib/wpa/src/utils/base64.c */
955
956
static const unsigned char base64_table[65] =
957
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
958
959
/**
960
 * base64_decode - Base64 decode
961
 * @src: Data to be decoded
962
 * @len: Length of the data to be decoded
963
 * @out_len: Pointer to output length variable (NULL character at the end is ignored)
964
 * Returns: Allocated buffer of out_len bytes of decoded data,
965
 * or %NULL on failure
966
 *
967
 * Caller is responsible for freeing the returned buffer.
968
 * The returned buffer is always NULL terminated
969
 */
970
359
u_char* ndpi_base64_decode(const u_char *src, size_t len, size_t *out_len) {
971
359
  u_char dtable[256], *out, *pos, block[4], tmp;
972
359
  size_t i, count, olen;
973
359
  int pad = 0;
974
975
359
  memset(dtable, 0x80, 256);
976
23.3k
  for(i = 0; i < sizeof(base64_table) - 1; i++)
977
22.9k
    dtable[base64_table[i]] = (u_char) i;
978
359
  dtable['='] = 0;
979
980
359
  count = 0;
981
3.17k
  for(i = 0; i < len; i++) {
982
2.81k
    if(dtable[src[i]] != 0x80)
983
1.51k
      count++;
984
2.81k
  }
985
986
359
  if(count == 0 || count % 4)
987
334
    return NULL;
988
989
25
  olen = count / 4 * 3 + 1; /* out is always NULL terminated */
990
25
  pos = out = ndpi_calloc(1, olen);
991
25
  if(out == NULL)
992
0
    return NULL;
993
994
25
  count = 0;
995
334
  for(i = 0; i < len; i++) {
996
311
    tmp = dtable[src[i]];
997
311
    if(tmp == 0x80)
998
139
      continue;
999
1000
172
    if(src[i] == '=')
1001
2
      pad++;
1002
172
    block[count] = tmp;
1003
172
    count++;
1004
172
    if(count == 4) {
1005
43
      *pos++ = (block[0] << 2) | (block[1] >> 4);
1006
43
      *pos++ = (block[1] << 4) | (block[2] >> 2);
1007
43
      *pos++ = (block[2] << 6) | block[3];
1008
43
      count = 0;
1009
43
      if(pad) {
1010
2
  if(pad == 1)
1011
2
    pos--;
1012
0
  else if(pad == 2)
1013
0
    pos -= 2;
1014
0
  else {
1015
    /* Invalid padding */
1016
0
    ndpi_free(out);
1017
0
    return NULL;
1018
0
  }
1019
2
  break;
1020
2
      }
1021
43
    }
1022
172
  }
1023
1024
25
  *out_len = pos - out;
1025
1026
25
  return out;
1027
25
}
1028
1029
/* ********************************** */
1030
1031
/* NOTE: caller MUST free returned pointer */
1032
0
char* ndpi_base64_encode(unsigned char const* bytes_to_encode, size_t in_len) {
1033
0
  size_t len = 0, ret_size;
1034
0
  char *ret;
1035
0
  int j, i = 0;
1036
0
  unsigned char char_array_3[3];
1037
0
  unsigned char char_array_4[4];
1038
1039
0
  ret_size = ((in_len+2)/3)*4;
1040
1041
0
  if((ret = (char*)ndpi_malloc(ret_size+1)) == NULL)
1042
0
    return NULL;
1043
1044
0
  while (in_len--) {
1045
0
    char_array_3[i++] = *(bytes_to_encode++);
1046
0
    if(i == 3) {
1047
0
      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
1048
0
      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
1049
0
      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
1050
0
      char_array_4[3] = char_array_3[2] & 0x3f;
1051
1052
0
      for(i = 0; i < 4; i++)
1053
0
        ret[len++] = base64_table[char_array_4[i]];
1054
0
      i = 0;
1055
0
    }
1056
0
  }
1057
1058
0
  if(i) {
1059
0
    for(j = i; j < 3; j++)
1060
0
      char_array_3[j] = '\0';
1061
1062
0
    char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
1063
0
    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
1064
0
    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
1065
0
    char_array_4[3] = char_array_3[2] & 0x3f;
1066
1067
0
    for(j = 0; (j < i + 1); j++)
1068
0
      ret[len++] = base64_table[char_array_4[j]];
1069
1070
0
    while((i++ < 3))
1071
0
      ret[len++] = '=';
1072
0
  }
1073
1074
0
  ret[len++] = '\0';
1075
1076
0
  return ret;
1077
0
}
1078
1079
/* ********************************** */
1080
1081
/* NOTE: caller MUST free returned pointer */
1082
0
char* ndpi_hex_encode(unsigned char const* bytes_to_encode, size_t in_len) {
1083
0
  size_t double_len = in_len * 2;
1084
0
  char *ret = (char*)ndpi_malloc(double_len+1);
1085
1086
0
  if(ret != NULL) {
1087
0
    u_int i, ret_idx = 0;
1088
1089
0
    for(i=0; i<in_len; i++) {
1090
0
      sprintf(&ret[ret_idx], "%02x", bytes_to_encode[i]);
1091
0
      ret_idx += 2;
1092
0
    }
1093
1094
0
    ret[ret_idx] = '\0';
1095
0
  }
1096
1097
0
  return(ret);
1098
0
}
1099
1100
/* ********************************** */
1101
1102
0
u_char* ndpi_hex_decode(const u_char *src, size_t len, size_t *out_len) {
1103
0
  u_char *ret;
1104
1105
0
  *out_len = len / 2;
1106
0
  ret = (u_char*)ndpi_malloc(*out_len+1);
1107
1108
0
  if(ret != NULL) {
1109
0
    u_int i, ret_idx = 0;
1110
1111
0
    for(i=0; i<*out_len; i++) {
1112
0
      sscanf((const char*)&src[ret_idx], "%02hhX", &ret[i]);
1113
0
      ret_idx += 2;
1114
0
    }
1115
1116
0
    ret[i] = '\0';
1117
0
  }
1118
1119
0
  return(ret);
1120
0
}
1121
1122
/* ********************************** */
1123
1124
void ndpi_serialize_risk(ndpi_serializer *serializer,
1125
0
                         ndpi_risk risk) {
1126
0
  u_int32_t i;
1127
1128
0
  if(risk == 0) {
1129
0
    return;
1130
0
  }
1131
1132
0
  ndpi_serialize_start_of_block(serializer, "flow_risk");
1133
0
  for(i = 0; i < NDPI_MAX_RISK; i++) {
1134
0
    ndpi_risk_enum r = (ndpi_risk_enum)i;
1135
1136
0
    if(NDPI_ISSET_BIT(risk, r)) {
1137
0
      ndpi_risk_info const * const risk_info = ndpi_risk2severity(r);
1138
0
      if(risk_info == NULL)
1139
0
        continue;
1140
1141
0
      ndpi_serialize_start_of_block_uint32(serializer, i);
1142
0
      ndpi_serialize_string_string(serializer, "risk", ndpi_risk2str(risk_info->risk));
1143
0
      ndpi_serialize_string_string(serializer, "severity", ndpi_severity2str(risk_info->severity));
1144
0
      ndpi_serialize_risk_score(serializer, r);
1145
0
      ndpi_serialize_end_of_block(serializer);
1146
0
    }
1147
0
  }
1148
1149
0
  ndpi_serialize_end_of_block(serializer);
1150
0
}
1151
1152
/* ********************************** */
1153
1154
void ndpi_serialize_risk_score(ndpi_serializer *serializer,
1155
0
                               ndpi_risk_enum risk) {
1156
0
  u_int16_t rs, rs_client = 0, rs_server = 0;
1157
1158
0
  if(risk == NDPI_NO_RISK) {
1159
0
    return;
1160
0
  }
1161
1162
0
  ndpi_serialize_start_of_block(serializer, "risk_score");
1163
0
  rs = ndpi_risk2score(risk, &rs_client, &rs_server);
1164
0
  ndpi_serialize_string_uint32(serializer, "total", rs);
1165
0
  ndpi_serialize_string_uint32(serializer, "client", rs_client);
1166
0
  ndpi_serialize_string_uint32(serializer, "server", rs_server);
1167
0
  ndpi_serialize_end_of_block(serializer);
1168
0
}
1169
1170
/* ********************************** */
1171
1172
void ndpi_serialize_confidence(ndpi_serializer *serializer,
1173
                               ndpi_confidence_t confidence)
1174
0
{
1175
0
  if(confidence == NDPI_CONFIDENCE_UNKNOWN) {
1176
0
    return;
1177
0
  }
1178
1179
0
  ndpi_serialize_start_of_block(serializer, "confidence");
1180
0
  ndpi_serialize_uint32_string(serializer, (u_int32_t)confidence, ndpi_confidence_get_name(confidence));
1181
0
  ndpi_serialize_end_of_block(serializer);
1182
0
}
1183
1184
/* ********************************** */
1185
1186
void ndpi_serialize_proto(struct ndpi_detection_module_struct *ndpi_struct,
1187
                          ndpi_serializer *serializer,
1188
                          ndpi_risk risk,
1189
                          ndpi_confidence_t confidence,
1190
                          ndpi_protocol l7_protocol)
1191
0
{
1192
0
  char buf[64];
1193
1194
0
  ndpi_serialize_risk(serializer, risk);
1195
0
  ndpi_serialize_confidence(serializer, confidence);
1196
0
  ndpi_serialize_string_string(serializer, "proto", ndpi_protocol2name(ndpi_struct, l7_protocol.proto, buf, sizeof(buf)));
1197
0
  ndpi_serialize_string_string(serializer, "proto_id", ndpi_protocol2id(l7_protocol.proto, buf, sizeof(buf)));
1198
0
  ndpi_serialize_string_string(serializer, "proto_by_ip", ndpi_get_proto_name(ndpi_struct,
1199
0
                                                                              l7_protocol.protocol_by_ip));
1200
0
  ndpi_serialize_string_uint32(serializer, "proto_by_ip_id", l7_protocol.protocol_by_ip);
1201
0
  ndpi_serialize_string_uint32(serializer, "encrypted", ndpi_is_encrypted_proto(ndpi_struct, l7_protocol.proto));
1202
0
  ndpi_serialize_string_string(serializer, "breed", ndpi_get_proto_breed_name(l7_protocol.breed));
1203
0
  ndpi_serialize_string_uint32(serializer, "category_id", l7_protocol.category);
1204
0
  ndpi_serialize_string_string(serializer, "category", ndpi_category_get_name(ndpi_struct, l7_protocol.category));
1205
0
}
1206
1207
/* ********************************** */
1208
1209
static void ndpi_tls2json(ndpi_serializer *serializer, struct ndpi_flow_struct *flow, bool is_tls_proto)
1210
0
{
1211
0
  if(flow->protos.tls_quic.ssl_version)
1212
0
  {
1213
0
    char buf[64];
1214
0
    char notBefore[32], notAfter[32];
1215
0
    struct tm a, b, *before = NULL, *after = NULL;
1216
0
    u_int i, off;
1217
0
    u_int8_t unknown_tls_version;
1218
0
    char version[16], unknown_cipher[8];
1219
1220
0
    ndpi_ssl_version2str(version, sizeof(version), flow->protos.tls_quic.ssl_version, &unknown_tls_version);
1221
1222
0
    if(flow->protos.tls_quic.notBefore)
1223
0
    {
1224
0
      before = ndpi_gmtime_r((const time_t *)&flow->protos.tls_quic.notBefore, &a);
1225
0
    }
1226
0
    if(flow->protos.tls_quic.notAfter)
1227
0
    {
1228
0
      after = ndpi_gmtime_r((const time_t *)&flow->protos.tls_quic.notAfter, &b);
1229
0
    }
1230
1231
0
    if(!unknown_tls_version)
1232
0
    {
1233
0
      ndpi_serialize_start_of_block(serializer, "tls");
1234
0
      ndpi_serialize_string_string(serializer, "version", version);
1235
1236
0
      if(flow->protos.tls_quic.server_names)
1237
0
      {
1238
0
        ndpi_serialize_string_string(serializer, "server_names",
1239
0
                                     flow->protos.tls_quic.server_names);
1240
0
      }
1241
1242
0
      if(before)
1243
0
      {
1244
0
        strftime(notBefore, sizeof(notBefore), "%Y-%m-%d %H:%M:%S", before);
1245
0
        ndpi_serialize_string_string(serializer, "notbefore", notBefore);
1246
0
      }
1247
1248
0
      if(after)
1249
0
      {
1250
0
        strftime(notAfter, sizeof(notAfter), "%Y-%m-%d %H:%M:%S", after);
1251
0
        ndpi_serialize_string_string(serializer, "notafter", notAfter);
1252
0
      }
1253
1254
0
      ndpi_serialize_string_string(serializer, "ja3s", flow->protos.tls_quic.ja3_server);
1255
0
      ndpi_serialize_string_string(serializer, "ja4", flow->protos.tls_quic.ja4_client);
1256
0
      ndpi_serialize_string_uint32(serializer, "unsafe_cipher", flow->protos.tls_quic.server_unsafe_cipher);
1257
0
      ndpi_serialize_string_string(serializer, "cipher",
1258
0
                                   ndpi_cipher2str(flow->protos.tls_quic.server_cipher, unknown_cipher));
1259
1260
0
      if(flow->protos.tls_quic.issuerDN)
1261
0
      {
1262
0
        ndpi_serialize_string_string(serializer, "issuerDN", flow->protos.tls_quic.issuerDN);
1263
0
      }
1264
0
      if(flow->protos.tls_quic.subjectDN)
1265
0
      {
1266
0
        ndpi_serialize_string_string(serializer, "subjectDN", flow->protos.tls_quic.subjectDN);
1267
0
      }
1268
0
      if(flow->protos.tls_quic.advertised_alpns)
1269
0
      {
1270
0
        ndpi_serialize_string_string(serializer, "advertised_alpns", flow->protos.tls_quic.advertised_alpns);
1271
0
      }
1272
0
      if(flow->protos.tls_quic.negotiated_alpn)
1273
0
      {
1274
0
        ndpi_serialize_string_string(serializer, "negotiated_alpn", flow->protos.tls_quic.negotiated_alpn);
1275
0
      }
1276
0
      if(flow->protos.tls_quic.tls_supported_versions)
1277
0
      {
1278
0
        ndpi_serialize_string_string(serializer, "tls_supported_versions", flow->protos.tls_quic.tls_supported_versions);
1279
0
      }
1280
1281
0
      if(flow->protos.tls_quic.sha1_certificate_fingerprint[0] != '\0')
1282
0
      {
1283
0
        for(i=0, off=0; i<20; i++)
1284
0
        {
1285
0
          int rc = ndpi_snprintf(&buf[off], sizeof(buf)-off,"%s%02X", (i > 0) ? ":" : "",
1286
0
                               flow->protos.tls_quic.sha1_certificate_fingerprint[i] & 0xFF);
1287
1288
0
          if(rc <= 0) break; else off += rc;
1289
0
        }
1290
1291
0
        ndpi_serialize_string_string(serializer, "fingerprint", buf);
1292
0
      }
1293
1294
0
      if (is_tls_proto == true)
1295
0
      {
1296
0
        ndpi_serialize_string_uint32(serializer, "blocks", flow->l4.tcp.tls.num_tls_blocks);
1297
0
      }
1298
0
#ifdef TLS_HANDLE_SIGNATURE_ALGORITMS
1299
0
      ndpi_serialize_string_uint32(serializer, "sig_algs", flow->protos.tls_quic.num_tls_signature_algorithms);
1300
0
#endif
1301
1302
0
      ndpi_serialize_end_of_block(serializer);
1303
0
    }
1304
0
  }
1305
0
}
1306
1307
/* ********************************** */
1308
1309
0
char* print_ndpi_address_port(ndpi_address_port *ap, char *buf, u_int buf_len) {
1310
0
  char ipbuf[INET6_ADDRSTRLEN];
1311
1312
0
  if(ap->is_ipv6) {
1313
0
    inet_ntop(AF_INET6, &ap->address, ipbuf, sizeof(ipbuf));
1314
0
  } else {
1315
0
    inet_ntop(AF_INET, &ap->address, ipbuf, sizeof(ipbuf));
1316
0
  }
1317
1318
0
  snprintf(buf, buf_len, "%s:%u", ipbuf, ap->port);
1319
1320
0
  return(buf);
1321
0
}
1322
1323
/* ********************************** */
1324
1325
/* NOTE: serializer must have been already initialized */
1326
int ndpi_dpi2json(struct ndpi_detection_module_struct *ndpi_struct,
1327
      struct ndpi_flow_struct *flow,
1328
      ndpi_protocol l7_protocol,
1329
0
      ndpi_serializer *serializer) {
1330
0
  char buf[64];
1331
0
  char const *host_server_name;
1332
0
  char quic_version[16];
1333
0
  char content[64] = {0};
1334
0
  u_int i;
1335
1336
0
  if(flow == NULL) return(-1);
1337
1338
0
  ndpi_serialize_start_of_block(serializer, "ndpi");
1339
0
  ndpi_serialize_proto(ndpi_struct, serializer, flow->risk, flow->confidence, l7_protocol);
1340
1341
0
  host_server_name = ndpi_get_flow_info(flow, &l7_protocol);
1342
1343
0
  if (host_server_name != NULL) {
1344
0
    ndpi_serialize_string_string(serializer, "hostname", host_server_name);
1345
0
    ndpi_serialize_string_string(serializer, "domainame", ndpi_get_host_domain(ndpi_struct, host_server_name));
1346
0
  }
1347
1348
0
  if(flow->flow_multimedia_types != ndpi_multimedia_unknown_flow) {
1349
0
    ndpi_serialize_string_string(serializer, "stream_content", ndpi_multimedia_flowtype2str(content, sizeof(content), flow->flow_multimedia_types));
1350
0
  }
1351
1352
0
  switch(l7_protocol.proto.master_protocol ? l7_protocol.proto.master_protocol : l7_protocol.proto.app_protocol) {
1353
0
  case NDPI_PROTOCOL_IP_ICMP:
1354
0
    if(flow->entropy > 0.0f) {
1355
0
      ndpi_serialize_string_float(serializer, "entropy", flow->entropy, "%.6f");
1356
0
    }
1357
0
    break;
1358
1359
0
  case NDPI_PROTOCOL_DHCP:
1360
0
    ndpi_serialize_start_of_block(serializer, "dhcp");
1361
0
    ndpi_serialize_string_string(serializer, "fingerprint", flow->protos.dhcp.fingerprint);
1362
0
    ndpi_serialize_string_string(serializer, "class_ident", flow->protos.dhcp.class_ident);
1363
0
    ndpi_serialize_end_of_block(serializer);
1364
0
    break;
1365
1366
0
  case NDPI_PROTOCOL_BITTORRENT:
1367
0
    {
1368
0
      u_int i, j, n = 0;
1369
0
      char bittorent_hash[sizeof(flow->protos.bittorrent.hash)*2+1];
1370
1371
0
      for(i=0, j = 0; j < sizeof(bittorent_hash)-1; i++) {
1372
0
  snprintf(&bittorent_hash[j],
1373
0
     sizeof(bittorent_hash) - j,
1374
0
     "%02x",
1375
0
    flow->protos.bittorrent.hash[i]);
1376
1377
0
  j += 2, n += flow->protos.bittorrent.hash[i];
1378
0
      }
1379
1380
0
      if(n == 0) bittorent_hash[0] = '\0';
1381
1382
0
      ndpi_serialize_start_of_block(serializer, "bittorrent");
1383
0
      ndpi_serialize_string_string(serializer, "hash", bittorent_hash);
1384
0
      ndpi_serialize_end_of_block(serializer);
1385
0
    }
1386
0
    break;
1387
1388
0
  case NDPI_PROTOCOL_COLLECTD:
1389
0
    ndpi_serialize_start_of_block(serializer, "collectd");
1390
0
    ndpi_serialize_string_string(serializer, "client_username", flow->protos.collectd.client_username);
1391
0
    ndpi_serialize_end_of_block(serializer);
1392
0
    break;
1393
1394
0
  case NDPI_PROTOCOL_DNS:
1395
0
    ndpi_serialize_start_of_block(serializer, "dns");
1396
0
    ndpi_serialize_string_uint32(serializer, "num_queries", flow->protos.dns.num_queries);
1397
0
    ndpi_serialize_string_uint32(serializer, "num_answers", flow->protos.dns.num_answers);
1398
0
    ndpi_serialize_string_uint32(serializer, "reply_code",  flow->protos.dns.reply_code);
1399
0
    ndpi_serialize_string_uint32(serializer, "query_type",  flow->protos.dns.query_type);
1400
0
    ndpi_serialize_string_uint32(serializer, "rsp_type",    flow->protos.dns.rsp_type);
1401
1402
0
    ndpi_serialize_start_of_list(serializer, "rsp_addr");
1403
1404
0
    for(i=0; i<flow->protos.dns.num_rsp_addr; i++) {
1405
0
      char buf[64];
1406
0
      u_int len;
1407
1408
0
      if(flow->protos.dns.is_rsp_addr_ipv6[i] == 0) {
1409
0
  inet_ntop(AF_INET, &flow->protos.dns.rsp_addr[i].ipv4, buf, sizeof(buf));
1410
0
      } else {
1411
0
  inet_ntop(AF_INET6, &flow->protos.dns.rsp_addr[i].ipv6, buf, sizeof(buf));
1412
0
      }
1413
1414
0
      len = strlen(buf);
1415
0
      snprintf(&buf[len], sizeof(buf)-len, ",ttl=%u", flow->protos.dns.rsp_addr_ttl[i]);
1416
0
      ndpi_serialize_string_string(serializer, "addr", buf);
1417
0
    }
1418
1419
0
    ndpi_serialize_end_of_list(serializer);
1420
1421
0
    ndpi_serialize_end_of_block(serializer);
1422
0
    break;
1423
1424
0
  case NDPI_PROTOCOL_NTP:
1425
0
    ndpi_serialize_start_of_block(serializer, "ntp");
1426
0
    ndpi_serialize_string_uint32(serializer, "version", flow->protos.ntp.version);
1427
0
    ndpi_serialize_string_uint32(serializer, "mode", flow->protos.ntp.mode);
1428
0
    ndpi_serialize_end_of_block(serializer);
1429
0
    break;
1430
1431
0
  case NDPI_PROTOCOL_MDNS:
1432
0
    ndpi_serialize_start_of_block(serializer, "mdns");
1433
0
    ndpi_serialize_end_of_block(serializer);
1434
0
    break;
1435
1436
0
  case NDPI_PROTOCOL_UBNTAC2:
1437
0
    ndpi_serialize_start_of_block(serializer, "ubntac2");
1438
0
    ndpi_serialize_string_string(serializer, "version", flow->protos.ubntac2.version);
1439
0
    ndpi_serialize_end_of_block(serializer);
1440
0
    break;
1441
1442
0
  case NDPI_PROTOCOL_KERBEROS:
1443
0
    ndpi_serialize_start_of_block(serializer, "kerberos");
1444
0
    ndpi_serialize_string_string(serializer, "hostname", flow->protos.kerberos.hostname);
1445
0
    ndpi_serialize_string_string(serializer, "domain", flow->protos.kerberos.domain);
1446
0
    ndpi_serialize_string_string(serializer, "username", flow->protos.kerberos.username);
1447
0
    ndpi_serialize_end_of_block(serializer);
1448
0
    break;
1449
1450
0
  case NDPI_PROTOCOL_SOFTETHER:
1451
0
    ndpi_serialize_start_of_block(serializer, "softether");
1452
0
    ndpi_serialize_string_string(serializer, "client_ip", flow->protos.softether.ip);
1453
0
    ndpi_serialize_string_string(serializer, "client_port", flow->protos.softether.port);
1454
0
    ndpi_serialize_string_string(serializer, "hostname", flow->protos.softether.hostname);
1455
0
    ndpi_serialize_string_string(serializer, "fqdn", flow->protos.softether.fqdn);
1456
0
    ndpi_serialize_end_of_block(serializer);
1457
0
    break;
1458
1459
0
  case NDPI_PROTOCOL_NATPMP:
1460
0
    ndpi_serialize_start_of_block(serializer, "natpmp");
1461
0
    ndpi_serialize_string_uint32(serializer, "result", flow->protos.natpmp.result_code);
1462
0
    ndpi_serialize_string_uint32(serializer, "internal_port", flow->protos.natpmp.internal_port);
1463
0
    ndpi_serialize_string_uint32(serializer, "external_port", flow->protos.natpmp.external_port);
1464
0
    inet_ntop(AF_INET, &flow->protos.natpmp.external_address.ipv4, buf, sizeof(buf));
1465
0
    ndpi_serialize_string_string(serializer, "external_address", buf);
1466
0
    ndpi_serialize_end_of_block(serializer);
1467
0
    break;
1468
1469
0
  case NDPI_PROTOCOL_RSH:
1470
0
    ndpi_serialize_start_of_block(serializer, "rsh");
1471
0
    ndpi_serialize_string_string(serializer, "client_username", flow->protos.rsh.client_username);
1472
0
    ndpi_serialize_string_string(serializer, "server_username", flow->protos.rsh.server_username);
1473
0
    ndpi_serialize_string_string(serializer, "command", flow->protos.rsh.command);
1474
0
    ndpi_serialize_end_of_block(serializer);
1475
0
    break;
1476
1477
0
  case NDPI_PROTOCOL_SNMP:
1478
0
    ndpi_serialize_start_of_block(serializer, "snmp");
1479
0
    ndpi_serialize_string_uint32(serializer, "version", flow->protos.snmp.version);
1480
0
    ndpi_serialize_string_uint32(serializer, "primitive", flow->protos.snmp.primitive);
1481
0
    ndpi_serialize_string_uint32(serializer, "error_status", flow->protos.snmp.error_status);
1482
0
    ndpi_serialize_end_of_block(serializer);
1483
0
    break;
1484
1485
0
  case NDPI_PROTOCOL_TELNET:
1486
0
    ndpi_serialize_start_of_block(serializer, "telnet");
1487
0
    ndpi_serialize_string_string(serializer, "username", flow->protos.telnet.username);
1488
0
    ndpi_serialize_string_string(serializer, "password", flow->protos.telnet.password);
1489
0
    ndpi_serialize_end_of_block(serializer);
1490
0
    break;
1491
1492
0
  case NDPI_PROTOCOL_TFTP:
1493
0
    ndpi_serialize_start_of_block(serializer, "tftp");
1494
0
    ndpi_serialize_string_string(serializer, "filename", flow->protos.tftp.filename);
1495
0
    ndpi_serialize_end_of_block(serializer);
1496
0
    break;
1497
1498
0
  case NDPI_PROTOCOL_TIVOCONNECT:
1499
0
    ndpi_serialize_start_of_block(serializer, "tivoconnect");
1500
0
    ndpi_serialize_string_string(serializer, "identity_uuid", flow->protos.tivoconnect.identity_uuid);
1501
0
    ndpi_serialize_string_string(serializer, "machine", flow->protos.tivoconnect.machine);
1502
0
    ndpi_serialize_string_string(serializer, "platform", flow->protos.tivoconnect.platform);
1503
0
    ndpi_serialize_string_string(serializer, "services", flow->protos.tivoconnect.services);
1504
0
    ndpi_serialize_end_of_block(serializer);
1505
0
    break;
1506
1507
0
  case NDPI_PROTOCOL_HTTP:
1508
0
  case NDPI_PROTOCOL_HTTP_CONNECT:
1509
0
  case NDPI_PROTOCOL_HTTP_PROXY:
1510
0
    ndpi_serialize_start_of_block(serializer, "http");
1511
1512
0
    if(flow->http.url != NULL) {
1513
0
      ndpi_serialize_string_string(serializer, "url", flow->http.url);
1514
0
      ndpi_serialize_string_uint32(serializer, "code", flow->http.response_status_code);
1515
0
      ndpi_serialize_string_string(serializer, "content_type", flow->http.content_type);
1516
0
      ndpi_serialize_string_string(serializer, "user_agent", flow->http.user_agent);
1517
0
    }
1518
1519
0
    if (flow->http.request_content_type != NULL)
1520
0
      ndpi_serialize_string_string(serializer, "request_content_type",
1521
0
                                   flow->http.request_content_type);
1522
1523
0
    if (flow->http.detected_os != NULL)
1524
0
      ndpi_serialize_string_string(serializer, "detected_os",
1525
0
                                   flow->http.detected_os);
1526
1527
0
    if (flow->http.nat_ip != NULL)
1528
0
      ndpi_serialize_string_string(serializer, "nat_ip",
1529
0
                                   flow->http.nat_ip);
1530
1531
0
    ndpi_serialize_end_of_block(serializer);
1532
0
    break;
1533
1534
0
  case NDPI_PROTOCOL_QUIC:
1535
0
    ndpi_serialize_start_of_block(serializer, "quic");
1536
1537
0
    ndpi_quic_version2str(quic_version, sizeof(quic_version),
1538
0
                          flow->protos.tls_quic.quic_version);
1539
0
    ndpi_serialize_string_string(serializer, "quic_version", quic_version);
1540
1541
0
    ndpi_tls2json(serializer, flow, false);
1542
1543
0
    ndpi_serialize_end_of_block(serializer);
1544
0
    break;
1545
1546
0
  case NDPI_PROTOCOL_MAIL_IMAP:
1547
0
    ndpi_serialize_start_of_block(serializer, "imap");
1548
0
    ndpi_serialize_string_string(serializer,  "user", flow->l4.tcp.ftp_imap_pop_smtp.username);
1549
0
    ndpi_serialize_string_string(serializer,  "password", flow->l4.tcp.ftp_imap_pop_smtp.password);
1550
0
    ndpi_serialize_string_uint32(serializer, "auth_failed",
1551
0
                                 flow->l4.tcp.ftp_imap_pop_smtp.auth_failed);
1552
0
    ndpi_serialize_end_of_block(serializer);
1553
0
    break;
1554
1555
0
  case NDPI_PROTOCOL_MAIL_POP:
1556
0
    ndpi_serialize_start_of_block(serializer, "pop");
1557
0
    ndpi_serialize_string_string(serializer,  "user", flow->l4.tcp.ftp_imap_pop_smtp.username);
1558
0
    ndpi_serialize_string_string(serializer,  "password", flow->l4.tcp.ftp_imap_pop_smtp.password);
1559
0
    ndpi_serialize_string_uint32(serializer, "auth_failed",
1560
0
                                 flow->l4.tcp.ftp_imap_pop_smtp.auth_failed);
1561
0
    ndpi_serialize_end_of_block(serializer);
1562
0
    break;
1563
1564
0
  case NDPI_PROTOCOL_MAIL_SMTP:
1565
0
    ndpi_serialize_start_of_block(serializer, "smtp");
1566
0
    ndpi_serialize_string_string(serializer,  "user", flow->l4.tcp.ftp_imap_pop_smtp.username);
1567
0
    ndpi_serialize_string_string(serializer,  "password", flow->l4.tcp.ftp_imap_pop_smtp.password);
1568
0
    ndpi_serialize_string_uint32(serializer, "auth_failed",
1569
0
                                 flow->l4.tcp.ftp_imap_pop_smtp.auth_failed);
1570
0
    ndpi_serialize_end_of_block(serializer);
1571
0
    break;
1572
1573
0
  case NDPI_PROTOCOL_FTP_CONTROL:
1574
0
    ndpi_serialize_start_of_block(serializer, "ftp");
1575
0
    ndpi_serialize_string_string(serializer,  "user", flow->l4.tcp.ftp_imap_pop_smtp.username);
1576
0
    ndpi_serialize_string_string(serializer,  "password", flow->l4.tcp.ftp_imap_pop_smtp.password);
1577
0
    ndpi_serialize_string_uint32(serializer,  "auth_failed", flow->l4.tcp.ftp_imap_pop_smtp.auth_failed);
1578
0
    ndpi_serialize_end_of_block(serializer);
1579
0
    break;
1580
1581
0
  case NDPI_PROTOCOL_MIKROTIK:
1582
0
    {
1583
0
      char buf[32];
1584
1585
0
      ndpi_serialize_start_of_block(serializer, "mikrotik");
1586
1587
0
      snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X",
1588
0
         flow->protos.mikrotik.mac_addr[0] & 0xFF,
1589
0
         flow->protos.mikrotik.mac_addr[1] & 0xFF,
1590
0
         flow->protos.mikrotik.mac_addr[2] & 0xFF,
1591
0
         flow->protos.mikrotik.mac_addr[3] & 0xFF,
1592
0
         flow->protos.mikrotik.mac_addr[4] & 0xFF,
1593
0
         flow->protos.mikrotik.mac_addr[5] & 0xFF);
1594
1595
0
      ndpi_serialize_string_string(serializer, "mac_address", buf);
1596
1597
0
      if(flow->protos.mikrotik.identity[0] != '\0')
1598
0
  ndpi_serialize_string_string(serializer, "identity", flow->protos.mikrotik.identity);
1599
1600
0
      if(flow->protos.mikrotik.version[0] != '\0')
1601
0
  ndpi_serialize_string_string(serializer, "version", flow->protos.mikrotik.version);
1602
1603
0
      if(flow->protos.mikrotik.sw_id[0] != '\0')
1604
0
  ndpi_serialize_string_string(serializer, "software_id", flow->protos.mikrotik.sw_id);
1605
1606
0
      if(flow->protos.mikrotik.board[0] != '\0')
1607
0
  ndpi_serialize_string_string(serializer, "board", flow->protos.mikrotik.board);
1608
1609
0
      if(flow->protos.mikrotik.iface_name[0] != '\0')
1610
0
  ndpi_serialize_string_string(serializer, "iface_name", flow->protos.mikrotik.iface_name);
1611
1612
0
      if(flow->protos.mikrotik.ipv4_addr != 0)
1613
0
  ndpi_serialize_string_string(serializer, "ipv4_addr",
1614
0
             ndpi_intoav4(flow->protos.mikrotik.ipv4_addr, buf, sizeof(buf)));
1615
1616
0
      if(flow->protos.mikrotik.ipv6_addr.u6_addr.u6_addr64[0] != 0)
1617
0
  ndpi_serialize_string_string(serializer, "ipv6_addr",
1618
0
             ndpi_intoav6(&flow->protos.mikrotik.ipv6_addr, buf, sizeof(buf)));
1619
1620
0
      if(flow->protos.mikrotik.uptime != 0)
1621
0
  ndpi_serialize_string_uint32(serializer, "uptime", flow->protos.mikrotik.uptime);
1622
1623
0
      ndpi_serialize_end_of_block(serializer);
1624
0
    }
1625
0
    break;
1626
1627
0
  case NDPI_PROTOCOL_SSDP:
1628
0
    ndpi_serialize_start_of_block(serializer, "ssdp");
1629
1630
0
    if (flow->protos.ssdp.method) {
1631
0
      ndpi_serialize_string_string(serializer, "METHOD", flow->protos.ssdp.method);
1632
0
    }
1633
1634
0
    if (flow->protos.ssdp.cache_controle) {
1635
0
      ndpi_serialize_string_string(serializer, "CACHE-CONTROL", flow->protos.ssdp.cache_controle);
1636
0
    }
1637
1638
0
    if (flow->protos.ssdp.location) {
1639
0
      ndpi_serialize_string_string(serializer, "LOCATION", flow->protos.ssdp.location);
1640
0
    }
1641
1642
0
    if (flow->protos.ssdp.nt) {
1643
0
      ndpi_serialize_string_string(serializer, "NT", flow->protos.ssdp.nt);
1644
0
    }
1645
1646
0
    if (flow->protos.ssdp.nts) {
1647
0
      ndpi_serialize_string_string(serializer, "NTS", flow->protos.ssdp.nts);
1648
0
    }
1649
1650
0
    if (flow->protos.ssdp.server) {
1651
0
      ndpi_serialize_string_string(serializer, "SERVER", flow->protos.ssdp.server);
1652
0
    }
1653
1654
0
    if (flow->protos.ssdp.usn) {
1655
0
      ndpi_serialize_string_string(serializer, "USN", flow->protos.ssdp.usn);
1656
0
    }
1657
1658
0
    if (flow->protos.ssdp.rincon_household) {
1659
0
      ndpi_serialize_string_string(serializer, "X-RINCON-HOUSEHOLD", flow->protos.ssdp.rincon_household);
1660
0
    }
1661
1662
0
    if (flow->protos.ssdp.rincon_bootseq) {
1663
0
      ndpi_serialize_string_string(serializer, "X-RINCON-BOOTSEQ", flow->protos.ssdp.rincon_bootseq);
1664
0
    }
1665
1666
0
    if (flow->protos.ssdp.bootid) {
1667
0
      ndpi_serialize_string_string(serializer, "BOOTID.UPNP.ORG", flow->protos.ssdp.bootid);
1668
0
    }
1669
1670
0
    if (flow->protos.ssdp.rincon_wifimode) {
1671
0
      ndpi_serialize_string_string(serializer, "X-RINCON-WIFIMODE", flow->protos.ssdp.rincon_wifimode);
1672
0
    }
1673
1674
0
    if (flow->protos.ssdp.rincon_variant) {
1675
0
      ndpi_serialize_string_string(serializer, "X-RINCON-VARIANT", flow->protos.ssdp.rincon_variant);
1676
0
    }
1677
1678
0
    if (flow->protos.ssdp.household_smart_speaker_audio) {
1679
0
      ndpi_serialize_string_string(serializer, "HOUSEHOLD.SMARTSPEAKER.AUDIO", flow->protos.ssdp.household_smart_speaker_audio);
1680
0
    }
1681
1682
0
    if (flow->protos.ssdp.location_smart_speaker_audio) {
1683
0
      ndpi_serialize_string_string(serializer, "LOCATION.SMARTSPEAKER.AUDIO", flow->protos.ssdp.location_smart_speaker_audio);
1684
0
    }
1685
1686
0
    if (flow->protos.ssdp.securelocation_upnp) {
1687
0
      ndpi_serialize_string_string(serializer, "SECURELOCATION.UPNP.ORG", flow->protos.ssdp.securelocation_upnp);
1688
0
    }
1689
1690
0
    if (flow->protos.ssdp.sonos_securelocation) {
1691
0
      ndpi_serialize_string_string(serializer, "X-SONOS-HHSECURELOCATION", flow->protos.ssdp.sonos_securelocation);
1692
0
    }
1693
1694
0
    if (flow->protos.ssdp.man) {
1695
0
      ndpi_serialize_string_string(serializer, "MAN", flow->protos.ssdp.man);
1696
0
    }
1697
1698
0
    if (flow->protos.ssdp.mx) {
1699
0
      ndpi_serialize_string_string(serializer, "MX", flow->protos.ssdp.mx);
1700
0
    }
1701
1702
0
    if (flow->protos.ssdp.st) {
1703
0
      ndpi_serialize_string_string(serializer, "ST", flow->protos.ssdp.st);
1704
0
    }
1705
1706
0
    if (flow->protos.ssdp.user_agent) {
1707
0
      ndpi_serialize_string_string(serializer, "USER_AGENT", flow->protos.ssdp.user_agent);
1708
0
    }
1709
1710
0
    ndpi_serialize_end_of_block(serializer);
1711
0
    break;
1712
1713
0
  case NDPI_PROTOCOL_DISCORD:
1714
0
    if (l7_protocol.proto.master_protocol != NDPI_PROTOCOL_TLS) {
1715
0
      ndpi_serialize_start_of_block(serializer, "discord");
1716
0
      ndpi_serialize_string_string(serializer, "client_ip", flow->protos.discord.client_ip);
1717
0
      ndpi_serialize_end_of_block(serializer);
1718
0
    }
1719
0
    break;
1720
1721
0
  case NDPI_PROTOCOL_SSH:
1722
0
    ndpi_serialize_start_of_block(serializer, "ssh");
1723
0
    ndpi_serialize_string_string(serializer,  "client_signature", flow->protos.ssh.client_signature);
1724
0
    ndpi_serialize_string_string(serializer,  "server_signature", flow->protos.ssh.server_signature);
1725
0
    ndpi_serialize_string_string(serializer,  "hassh_client", flow->protos.ssh.hassh_client);
1726
0
    ndpi_serialize_string_string(serializer,  "hassh_server", flow->protos.ssh.hassh_server);
1727
0
    ndpi_serialize_end_of_block(serializer);
1728
0
    break;
1729
1730
0
  case NDPI_PROTOCOL_STUN:
1731
0
    ndpi_serialize_start_of_block(serializer, "stun");
1732
1733
0
    if(flow->stun.mapped_address.port)
1734
0
      ndpi_serialize_string_string(serializer,  "mapped_address", print_ndpi_address_port(&flow->stun.mapped_address, buf, sizeof(buf)));
1735
1736
0
    if(flow->stun.peer_address.port)
1737
0
      ndpi_serialize_string_string(serializer,  "peer_address", print_ndpi_address_port(&flow->stun.peer_address, buf, sizeof(buf)));
1738
1739
0
    if(flow->stun.relayed_address.port)
1740
0
      ndpi_serialize_string_string(serializer,  "relayed_address", print_ndpi_address_port(&flow->stun.relayed_address, buf, sizeof(buf)));
1741
1742
0
    if(flow->stun.response_origin.port)
1743
0
      ndpi_serialize_string_string(serializer,  "response_origin", print_ndpi_address_port(&flow->stun.response_origin, buf, sizeof(buf)));
1744
1745
0
    if(flow->stun.other_address.port)
1746
0
      ndpi_serialize_string_string(serializer,  "other_address", print_ndpi_address_port(&flow->stun.other_address, buf, sizeof(buf)));
1747
1748
0
    ndpi_serialize_string_string(serializer,  "multimedia_flow_types",
1749
0
         ndpi_multimedia_flowtype2str(content, sizeof(content), flow->flow_multimedia_types));
1750
1751
#ifdef CUSTOM_NDPI_PROTOCOLS
1752
#include "../../../nDPI-custom/ndpi_utils_dpi2json_stun.c"
1753
#endif
1754
1755
0
    ndpi_serialize_end_of_block(serializer);
1756
0
    break;
1757
1758
0
  case NDPI_PROTOCOL_SIP:
1759
0
    ndpi_serialize_start_of_block(serializer, "sip");
1760
0
    if(flow->protos.sip.from)
1761
0
      ndpi_serialize_string_string(serializer, "from", flow->protos.sip.from);
1762
0
    if(flow->protos.sip.from_imsi[0] != '\0')
1763
0
      ndpi_serialize_string_string(serializer, "from_imsi", flow->protos.sip.from_imsi);
1764
0
    if(flow->protos.sip.to)
1765
0
      ndpi_serialize_string_string(serializer, "to", flow->protos.sip.to);
1766
0
    if(flow->protos.sip.to_imsi[0] != '\0')
1767
0
      ndpi_serialize_string_string(serializer, "to_imsi", flow->protos.sip.to_imsi);
1768
0
    ndpi_serialize_end_of_block(serializer);
1769
0
    break;
1770
1771
0
  case NDPI_PROTOCOL_TLS:
1772
0
    ndpi_tls2json(serializer, flow, true);
1773
0
    break;
1774
1775
0
  case NDPI_PROTOCOL_DTLS:
1776
0
    ndpi_tls2json(serializer, flow, false);
1777
#ifdef CUSTOM_NDPI_PROTOCOLS
1778
#include "../../../nDPI-custom/ndpi_utils_dpi2json_dtls.c"
1779
#endif
1780
0
    break;
1781
1782
#ifdef CUSTOM_NDPI_PROTOCOLS
1783
#include "../../../nDPI-custom/ndpi_utils_dpi2json_protos.c"
1784
#endif
1785
0
  } /* switch */
1786
1787
0
  ndpi_serialize_end_of_block(serializer); // "ndpi"
1788
1789
0
  return(0);
1790
0
}
1791
1792
/* ********************************** */
1793
1794
765
char *ndpi_get_ip_proto_name(u_int16_t ip_proto, char *name, unsigned int name_len) {
1795
765
  if(name == NULL || name_len == 0)
1796
488
    return name;
1797
1798
277
  switch (ip_proto) {
1799
2
  case IPPROTO_TCP:
1800
2
    snprintf(name, name_len, "TCP");
1801
2
    break;
1802
1803
0
  case IPPROTO_UDP:
1804
0
    snprintf(name, name_len, "UDP");
1805
0
    break;
1806
1807
0
  case NDPI_IPSEC_PROTOCOL_ESP:
1808
0
    snprintf(name, name_len, "ESP");
1809
0
    break;
1810
1811
0
  case NDPI_IPSEC_PROTOCOL_AH:
1812
0
    snprintf(name, name_len, "AH");
1813
0
    break;
1814
1815
2
  case NDPI_GRE_PROTOCOL_TYPE:
1816
2
    snprintf(name, name_len, "GRE");
1817
2
    break;
1818
1819
6
  case NDPI_ICMP_PROTOCOL_TYPE:
1820
6
    snprintf(name, name_len, "ICMP");
1821
6
    break;
1822
1823
2
  case NDPI_IGMP_PROTOCOL_TYPE:
1824
2
    snprintf(name, name_len, "IGMP");
1825
2
    break;
1826
1827
0
  case NDPI_EGP_PROTOCOL_TYPE:
1828
0
    snprintf(name, name_len, "EGP");
1829
0
    break;
1830
1831
0
  case NDPI_SCTP_PROTOCOL_TYPE:
1832
0
    snprintf(name, name_len, "SCTP");
1833
0
    break;
1834
1835
0
  case NDPI_PGM_PROTOCOL_TYPE:
1836
0
    snprintf(name, name_len, "PGM");
1837
0
    break;
1838
1839
0
  case NDPI_OSPF_PROTOCOL_TYPE:
1840
0
    snprintf(name, name_len, "OSPF");
1841
0
    break;
1842
1843
0
  case NDPI_IPIP_PROTOCOL_TYPE:
1844
0
    snprintf(name, name_len, "IPIP");
1845
0
    break;
1846
1847
2
  case NDPI_ICMPV6_PROTOCOL_TYPE:
1848
2
    snprintf(name, name_len, "ICMPV6");
1849
2
    break;
1850
1851
1
  case NDPI_PIM_PROTOCOL_TYPE:
1852
1
    snprintf(name, name_len, "PIM");
1853
1
    break;
1854
1855
0
  case NDPI_VRRP_PROTOCOL_TYPE:
1856
0
    snprintf(name, name_len, "VRRP");
1857
0
    break;
1858
1859
262
  default:
1860
262
    snprintf(name, name_len, "%d", ip_proto);
1861
262
    break;
1862
277
  }
1863
1864
277
  name[name_len - 1] = '\0';
1865
277
  return name;
1866
277
}
1867
1868
/* ********************************** */
1869
1870
/* NOTE: serializer is initialized by the function */
1871
int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct,
1872
       struct ndpi_flow_struct *flow,
1873
       u_int8_t ip_version,
1874
       u_int8_t l4_protocol,
1875
       u_int16_t vlan_id,
1876
       u_int32_t src_v4, u_int32_t dst_v4,
1877
       struct ndpi_in6_addr *src_v6, struct ndpi_in6_addr *dst_v6,
1878
       u_int16_t src_port, u_int16_t dst_port,
1879
       ndpi_protocol l7_protocol,
1880
0
       ndpi_serializer *serializer) {
1881
0
  char src_name[INET6_ADDRSTRLEN] = {'\0'}, dst_name[INET6_ADDRSTRLEN] = {'\0'};
1882
0
  char l4_proto_name[32];
1883
1884
0
  if(ip_version == 4) {
1885
0
    inet_ntop(AF_INET, &src_v4, src_name, sizeof(src_name));
1886
0
    inet_ntop(AF_INET, &dst_v4, dst_name, sizeof(dst_name));
1887
0
  } else {
1888
0
    inet_ntop(AF_INET6, src_v6, src_name, sizeof(src_name));
1889
0
    inet_ntop(AF_INET6, dst_v6, dst_name, sizeof(dst_name));
1890
    /* For consistency across platforms replace :0: with :: */
1891
0
    ndpi_patchIPv6Address(src_name), ndpi_patchIPv6Address(dst_name);
1892
0
  }
1893
1894
0
  if(vlan_id != 0) ndpi_serialize_string_uint32(serializer, "vlan_id", vlan_id);
1895
0
  ndpi_serialize_string_string(serializer, "src_ip", src_name);
1896
0
  ndpi_serialize_string_string(serializer, "dest_ip", dst_name);
1897
0
  if(src_port) ndpi_serialize_string_uint32(serializer, "src_port", ntohs(src_port));
1898
0
  if(dst_port) ndpi_serialize_string_uint32(serializer, "dst_port", ntohs(dst_port));
1899
1900
0
  ndpi_serialize_string_uint32(serializer, "ip", ip_version);
1901
1902
0
  if(flow->tcp.fingerprint)
1903
0
    ndpi_serialize_string_string(serializer, "tcp_fingerprint", flow->tcp.fingerprint);
1904
1905
0
  if(flow->tcp.fingerprint_raw)
1906
0
    ndpi_serialize_string_string(serializer, "tcp_fingerprint_raw", flow->tcp.fingerprint_raw);
1907
1908
0
  if(flow->ndpi.fingerprint)
1909
0
    ndpi_serialize_string_string(serializer, "ndpi_fingerprint", flow->ndpi.fingerprint);
1910
1911
0
  ndpi_serialize_string_string(serializer, "proto",
1912
0
             ndpi_get_ip_proto_name(l4_protocol, l4_proto_name, sizeof(l4_proto_name)));
1913
1914
0
  return(ndpi_dpi2json(ndpi_struct, flow, l7_protocol, serializer));
1915
0
}
1916
1917
/* ********************************** */
1918
1919
765
const char* ndpi_tunnel2str(ndpi_packet_tunnel tt) {
1920
765
  switch(tt) {
1921
292
  case ndpi_no_tunnel:
1922
292
    return("No-Tunnel");
1923
1924
84
  case ndpi_gtp_tunnel:
1925
84
    return("GTP");
1926
1927
54
  case ndpi_capwap_tunnel:
1928
54
    return("CAPWAP");
1929
1930
51
  case ndpi_tzsp_tunnel:
1931
51
    return("TZSP");
1932
1933
53
  case ndpi_l2tp_tunnel:
1934
53
    return("L2TP");
1935
1936
53
  case ndpi_vxlan_tunnel:
1937
53
    return("VXLAN");
1938
1939
69
  case ndpi_gre_tunnel:
1940
69
    return("GRE");
1941
765
  }
1942
1943
109
  return("");
1944
765
}
1945
1946
/* ********************************** */
1947
1948
/*
1949
  /dv/vulnerabilities/xss_r/?name=%3Cscript%3Econsole.log%28%27JUL2D3WXHEGWRAFJE2PI7OS71Z4Z8RFUHXGNFLUFYVP6M3OL55%27%29%3Bconsole.log%28document.cookie%29%3B%3C%2Fscript%3E
1950
  /dv/vulnerabilities/sqli/?id=1%27+and+1%3D1+union+select+null%2C+table_name+from+information_schema.tables%23&Submit=Submit
1951
*/
1952
1953
/* https://www.rosettacode.org/wiki/URL_decoding#C */
1954
0
static int ishex(int x) {
1955
0
  return(x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F');
1956
0
}
1957
1958
/* ********************************** */
1959
1960
254
static int ndpi_url_decode(const char *s, char *out) {
1961
254
  char *o;
1962
254
  const char *end = s + strlen(s);
1963
254
  int c;
1964
1965
55.8k
  for(o = out; s <= end; o++) {
1966
55.6k
    c = *s++;
1967
55.6k
    if(c == '+') c = ' ';
1968
55.4k
    else if(c == '%' && (!ishex(*s++)||
1969
0
       !ishex(*s++)||
1970
0
       (sscanf(s - 2, "%2x", (unsigned int*)&c) != 1)))
1971
0
      return(-1);
1972
1973
55.6k
    if(out) *o = c;
1974
55.6k
  }
1975
1976
254
  return(o - out);
1977
254
}
1978
1979
/* ********************************** */
1980
1981
248
static int ndpi_is_sql_injection(char* query) {
1982
248
  struct libinjection_sqli_state state;
1983
1984
248
  size_t qlen = strlen(query);
1985
248
  libinjection_sqli_init(&state, query, qlen, FLAG_NONE);
1986
1987
248
  return libinjection_is_sqli(&state);
1988
248
}
1989
1990
/* ********************************** */
1991
1992
254
static int ndpi_is_xss_injection(char* query) {
1993
254
  size_t qlen = strlen(query);
1994
254
  return libinjection_xss(query, qlen);
1995
254
}
1996
1997
/* ********************************** */
1998
1999
#ifdef HAVE_PCRE2
2000
2001
static void ndpi_compile_rce_regex() {
2002
  PCRE2_UCHAR pcreErrorStr[128];
2003
  PCRE2_SIZE pcreErrorOffset;
2004
  int i, pcreErrorCode = 0;
2005
2006
  for(i = 0; i < N_RCE_REGEX; i++) {
2007
    comp_rx[i] = (struct pcre2_struct*)ndpi_malloc(sizeof(struct pcre2_struct));
2008
2009
    comp_rx[i]->compiled = pcre2_compile((PCRE2_SPTR)rce_regex[i], PCRE2_ZERO_TERMINATED, 0, &pcreErrorCode,
2010
                                        &pcreErrorOffset, NULL);
2011
    pcre2_get_error_message(pcreErrorCode, pcreErrorStr, 128);
2012
    if(comp_rx[i]->compiled == NULL) {
2013
#ifdef DEBUG
2014
      NDPI_LOG_ERR(ndpi_str, "ERROR: Could not compile '%s': %s\n", rce_regex[i],
2015
                   pcreErrorStr);
2016
#endif
2017
2018
      continue;
2019
    }
2020
2021
    pcreErrorCode = pcre2_jit_compile(comp_rx[i]->compiled, PCRE2_JIT_COMPLETE);
2022
2023
#ifdef DEBUG
2024
    if(pcreErrorCode < 0) {
2025
      pcre2_get_error_message(pcreErrorCode, pcreErrorStr, 128);
2026
      NDPI_LOG_ERR(ndpi_str, "ERROR: Could not jit compile '%s': %s\n", rce_regex[i],
2027
                   pcreErrorStr);
2028
    }
2029
#endif
2030
  }
2031
}
2032
2033
/* ********************************** */
2034
2035
static int ndpi_is_rce_injection(char* query) {
2036
  if(!initialized_comp_rx) {
2037
    ndpi_compile_rce_regex();
2038
    initialized_comp_rx = 1;
2039
  }
2040
2041
  pcre2_match_data *pcreMatchData;
2042
  int i, pcreExecRet;
2043
  unsigned long j;
2044
2045
  for(i = 0; i < N_RCE_REGEX; i++) {
2046
    unsigned int length = strlen(query);
2047
2048
    pcreMatchData = pcre2_match_data_create_from_pattern(comp_rx[i]->compiled, NULL);
2049
    pcreExecRet = pcre2_match(comp_rx[i]->compiled,
2050
                            (PCRE2_SPTR)query, length, 0, 0, pcreMatchData, NULL);
2051
    pcre2_match_data_free(pcreMatchData);
2052
    if(pcreExecRet > 0) {
2053
      return 1;
2054
    }
2055
#ifdef DEBUG
2056
    else {
2057
      switch(pcreExecRet) {
2058
      case PCRE_ERROR_NOMATCH:
2059
  NDPI_LOG_ERR(ndpi_str, "ERROR: String did not match the pattern\n");
2060
  break;
2061
      case PCRE_ERROR_NULL:
2062
  NDPI_LOG_ERR(ndpi_str, "ERROR: Something was null\n");
2063
  break;
2064
      case PCRE_ERROR_BADOPTION:
2065
  NDPI_LOG_ERR(ndpi_str, "ERROR: A bad option was passed\n");
2066
  break;
2067
      case PCRE_ERROR_BADMAGIC:
2068
  NDPI_LOG_ERR(ndpi_str, "ERROR: Magic number bad (compiled re corrupt?)\n");
2069
  break;
2070
      case PCRE_ERROR_UNKNOWN_NODE:
2071
  NDPI_LOG_ERR(ndpi_str, "ERROR: Something kooky in the compiled re\n");
2072
  break;
2073
      case PCRE_ERROR_NOMEMORY:
2074
  NDPI_LOG_ERR(ndpi_str, "ERROR: Ran out of memory\n");
2075
  break;
2076
      default:
2077
  NDPI_LOG_ERR(ndpi_str, "ERROR: Unknown error\n");
2078
  break;
2079
      }
2080
    }
2081
#endif
2082
  }
2083
2084
  size_t ushlen = sizeof(ush_commands) / sizeof(ush_commands[0]);
2085
2086
  for(j = 0; j < ushlen; j++) {
2087
    if(strstr(query, ush_commands[j]) != NULL) {
2088
      return 1;
2089
    }
2090
  }
2091
2092
  size_t pwshlen = sizeof(pwsh_commands) / sizeof(pwsh_commands[0]);
2093
2094
  for(j = 0; j < pwshlen; j++) {
2095
    if(strstr(query, pwsh_commands[j]) != NULL) {
2096
      return 1;
2097
    }
2098
  }
2099
2100
  return 0;
2101
}
2102
2103
#endif
2104
2105
/* ********************************** */
2106
2107
ndpi_risk_enum ndpi_validate_url(struct ndpi_detection_module_struct *ndpi_str,
2108
         struct ndpi_flow_struct *flow,
2109
141
         char *url) {
2110
141
  char *orig_str = NULL, *str = NULL, *question_mark = strchr(url, '?');
2111
141
  ndpi_risk_enum rc = NDPI_NO_RISK;
2112
2113
141
  if(question_mark) {
2114
140
    char *tmp;
2115
2116
140
    orig_str = str = ndpi_strdup(&question_mark[1]); /* Skip ? */
2117
2118
140
    if(!str) goto validate_rc;
2119
2120
140
    str = strtok_r(str, "&", &tmp);
2121
2122
386
    while(str != NULL) {
2123
263
      char *value = strchr(str, '=');
2124
263
      char *decoded;
2125
2126
263
      if(!value)
2127
9
  break;
2128
254
      else
2129
254
  value = &value[1];
2130
2131
254
      if(value[0] != '\0') {
2132
254
  if(!(decoded = (char*)ndpi_malloc(strlen(value)+1)))
2133
0
    break;
2134
2135
254
  if(ndpi_url_decode(value, decoded) < 0) {
2136
    /* Invalid string */
2137
254
  } else if(decoded[0] != '\0') {
2138
    /* Valid string */
2139
2140
254
    if(ndpi_is_xss_injection(decoded))
2141
6
      rc = NDPI_URL_POSSIBLE_XSS;
2142
248
    else if(ndpi_is_sql_injection(decoded))
2143
2
      rc = NDPI_URL_POSSIBLE_SQL_INJECTION;
2144
#ifdef HAVE_PCRE2
2145
    else if(ndpi_is_rce_injection(decoded))
2146
      rc = NDPI_URL_POSSIBLE_RCE_INJECTION;
2147
#endif
2148
2149
#ifdef URL_CHECK_DEBUG
2150
    printf("=>> [rc: %u] %s\n", rc, decoded);
2151
#endif
2152
254
  }
2153
2154
254
  ndpi_free(decoded);
2155
2156
254
  if(rc != NDPI_NO_RISK) {
2157
8
    if(flow != NULL) {
2158
8
      char msg[128];
2159
2160
8
      snprintf(msg, sizeof(msg), "Suspicious URL [%s]", url);
2161
8
      ndpi_set_risk(ndpi_str, flow, rc, msg);
2162
8
    }
2163
8
    break;
2164
8
  }
2165
254
      }
2166
2167
246
      str = strtok_r(NULL, "&", &tmp);
2168
246
    }
2169
140
  }
2170
2171
141
 validate_rc:
2172
141
  if(orig_str) ndpi_free(orig_str);
2173
2174
141
  if(rc == NDPI_NO_RISK) {
2175
    /* Let's do an extra check */
2176
133
    if(strstr(url, "..")) {
2177
      /* 127.0.0.1/msadc/..%255c../..%255c../..%255c../winnt/system32/cmd.exe */
2178
0
      rc = NDPI_HTTP_SUSPICIOUS_URL;
2179
0
    }
2180
133
  }
2181
2182
141
  return(rc);
2183
141
}
2184
2185
/* ******************************************************************** */
2186
2187
765
u_int8_t ndpi_is_protocol_detected(ndpi_protocol proto) {
2188
765
  if((proto.proto.master_protocol != NDPI_PROTOCOL_UNKNOWN)
2189
329
     || (proto.proto.app_protocol != NDPI_PROTOCOL_UNKNOWN)
2190
321
     || (proto.category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED))
2191
444
    return(1);
2192
321
  else
2193
321
    return(0);
2194
765
}
2195
2196
/* ******************************************************************** */
2197
2198
27.8k
const char* ndpi_risk2str(ndpi_risk_enum risk) {
2199
27.8k
  static char buf[16];
2200
2201
27.8k
  switch(risk) {
2202
488
  case NDPI_URL_POSSIBLE_XSS:
2203
488
    return("XSS Attack");
2204
2205
483
  case NDPI_URL_POSSIBLE_SQL_INJECTION:
2206
483
    return("SQL Injection");
2207
2208
483
  case NDPI_URL_POSSIBLE_RCE_INJECTION:
2209
483
    return("RCE Injection");
2210
2211
484
  case NDPI_BINARY_APPLICATION_TRANSFER:
2212
484
    return("Binary App Transfer");
2213
2214
483
  case NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT:
2215
483
    return("Known Proto on Non Std Port");
2216
2217
484
  case NDPI_TLS_SELFSIGNED_CERTIFICATE:
2218
484
    return("Self-signed Cert");
2219
2220
484
  case NDPI_TLS_OBSOLETE_VERSION:
2221
484
    return("Obsolete TLS (v1.1 or older)");
2222
2223
484
  case NDPI_TLS_WEAK_CIPHER:
2224
484
    return("Weak TLS Cipher");
2225
2226
483
  case NDPI_TLS_CERTIFICATE_EXPIRED:
2227
483
    return("TLS Cert Expired");
2228
2229
483
  case NDPI_TLS_CERTIFICATE_MISMATCH:
2230
483
    return("TLS Cert Mismatch");
2231
2232
483
  case NDPI_HTTP_SUSPICIOUS_USER_AGENT:
2233
483
    return("HTTP Susp User-Agent");
2234
2235
484
  case NDPI_NUMERIC_IP_HOST:
2236
484
    return("HTTP/TLS/QUIC Numeric Hostname/SNI");
2237
2238
483
  case NDPI_HTTP_SUSPICIOUS_URL:
2239
483
    return("HTTP Susp URL");
2240
2241
483
  case NDPI_HTTP_SUSPICIOUS_HEADER:
2242
483
    return("HTTP Susp Header");
2243
2244
483
  case NDPI_TLS_NOT_CARRYING_HTTPS:
2245
483
    return("TLS (probably) Not Carrying HTTPS");
2246
2247
484
  case NDPI_SUSPICIOUS_DGA_DOMAIN:
2248
484
    return("Susp DGA Domain name");
2249
2250
483
  case NDPI_MALFORMED_PACKET:
2251
483
    return("Malformed Packet");
2252
2253
483
  case NDPI_SSH_OBSOLETE_CLIENT_VERSION_OR_CIPHER:
2254
483
    return("SSH Obsolete Cli Vers/Cipher");
2255
2256
483
  case NDPI_SSH_OBSOLETE_SERVER_VERSION_OR_CIPHER:
2257
483
    return("SSH Obsolete Ser Vers/Cipher");
2258
2259
483
  case NDPI_SMB_INSECURE_VERSION:
2260
483
    return("SMB Insecure Vers");
2261
2262
483
  case NDPI_MISMATCHING_PROTOCOL_WITH_IP:
2263
483
    return("Mismatching Protocol with server IP address");
2264
2265
483
  case NDPI_UNSAFE_PROTOCOL:
2266
483
    return("Unsafe Protocol");
2267
2268
483
  case NDPI_DNS_SUSPICIOUS_TRAFFIC:
2269
483
    return("Susp DNS Traffic"); /* Exfiltration ? */
2270
2271
483
  case NDPI_TLS_MISSING_SNI:
2272
483
    return("Missing SNI TLS Extn");
2273
2274
483
  case NDPI_HTTP_SUSPICIOUS_CONTENT:
2275
483
    return("HTTP Susp Content");
2276
2277
483
  case NDPI_RISKY_ASN:
2278
483
    return("Risky ASN");
2279
2280
483
  case NDPI_RISKY_DOMAIN:
2281
483
    return("Risky Domain Name");
2282
2283
483
  case NDPI_MALICIOUS_FINGERPRINT:
2284
483
    return("Malicious Fingerprint");
2285
2286
483
  case NDPI_MALICIOUS_SHA1_CERTIFICATE:
2287
483
    return("Malicious SSL Cert/SHA1 Fingerp.");
2288
2289
483
  case NDPI_DESKTOP_OR_FILE_SHARING_SESSION:
2290
483
    return("Desktop/File Sharing");
2291
2292
483
  case NDPI_TLS_UNCOMMON_ALPN:
2293
483
    return("Uncommon TLS ALPN");
2294
2295
483
  case NDPI_TLS_CERT_VALIDITY_TOO_LONG:
2296
483
    return("TLS Cert Validity Too Long");
2297
2298
483
  case NDPI_TLS_SUSPICIOUS_EXTENSION:
2299
483
    return("TLS Susp Extn");
2300
2301
483
  case NDPI_TLS_FATAL_ALERT:
2302
483
    return("TLS Fatal Alert");
2303
2304
483
  case NDPI_SUSPICIOUS_ENTROPY:
2305
483
    return("Susp Entropy");
2306
2307
483
  case NDPI_CLEAR_TEXT_CREDENTIALS:
2308
483
    return("Clear-Text Credentials");
2309
2310
483
  case NDPI_DNS_LARGE_PACKET:
2311
483
    return("Large DNS Packet (512+ bytes)");
2312
2313
483
  case NDPI_DNS_FRAGMENTED:
2314
483
    return("Fragmented DNS Message");
2315
2316
483
  case NDPI_INVALID_CHARACTERS:
2317
483
    return("Non-Printable/Invalid Chars Detected");
2318
2319
483
  case NDPI_POSSIBLE_EXPLOIT:
2320
483
    return("Possible Exploit Attempt");
2321
2322
483
  case NDPI_TLS_CERTIFICATE_ABOUT_TO_EXPIRE:
2323
483
    return("TLS Cert About To Expire");
2324
2325
483
  case NDPI_PUNYCODE_IDN:
2326
483
    return("IDN Domain Name");
2327
2328
483
  case NDPI_ERROR_CODE_DETECTED:
2329
483
    return("Error Code");
2330
2331
483
  case NDPI_HTTP_CRAWLER_BOT:
2332
483
    return("Crawler/Bot");
2333
2334
483
  case NDPI_ANONYMOUS_SUBSCRIBER:
2335
483
    return("Anonymous Subscriber");
2336
2337
483
  case NDPI_UNIDIRECTIONAL_TRAFFIC:
2338
483
    return("Unidirectional Traffic");
2339
2340
484
  case NDPI_HTTP_OBSOLETE_SERVER:
2341
484
    return("HTTP Obsolete Server");
2342
2343
484
  case NDPI_PERIODIC_FLOW:
2344
484
    return("Periodic Flow");
2345
2346
484
  case NDPI_MINOR_ISSUES:
2347
484
    return("Minor Issues");
2348
2349
483
  case NDPI_TCP_ISSUES:
2350
483
    return("TCP Connection Issues");
2351
2352
484
  case NDPI_UNRESOLVED_HOSTNAME:
2353
484
    return("Unresolved hostname");
2354
2355
484
  case NDPI_TLS_ALPN_SNI_MISMATCH:
2356
484
    return("ALPN/SNI Mismatch");
2357
2358
483
  case NDPI_MALWARE_HOST_CONTACTED:
2359
483
    return("Client Contacted A Malware Host");
2360
2361
483
  case NDPI_BINARY_DATA_TRANSFER:
2362
483
    return("Binary File/Data Transfer (Attempt)");
2363
2364
483
  case NDPI_PROBING_ATTEMPT:
2365
483
    return("Probing Attempt");
2366
2367
483
  case NDPI_OBFUSCATED_TRAFFIC:
2368
483
    return("Obfuscated Traffic");
2369
2370
749
  default:
2371
749
    ndpi_snprintf(buf, sizeof(buf), "%d", (int)risk);
2372
749
    return(buf);
2373
27.8k
  }
2374
27.8k
}
2375
2376
/* ******************************************************************** */
2377
2378
70.5k
#define STRINGIFY(x) #x
2379
2380
27.8k
const char* ndpi_risk2code(ndpi_risk_enum risk) {
2381
27.8k
  switch(risk) {
2382
339
  case NDPI_NO_RISK:
2383
339
    return STRINGIFY(NDPI_NO_RISK);
2384
478
  case NDPI_URL_POSSIBLE_XSS:
2385
478
    return STRINGIFY(NDPI_URL_POSSIBLE_XSS);
2386
478
  case NDPI_URL_POSSIBLE_SQL_INJECTION:
2387
478
    return STRINGIFY(NDPI_URL_POSSIBLE_SQL_INJECTION);
2388
478
  case NDPI_URL_POSSIBLE_RCE_INJECTION:
2389
478
    return STRINGIFY(NDPI_URL_POSSIBLE_RCE_INJECTION);
2390
486
  case NDPI_BINARY_APPLICATION_TRANSFER:
2391
486
    return STRINGIFY(NDPI_BINARY_APPLICATION_TRANSFER);
2392
475
  case NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT:
2393
475
    return STRINGIFY(NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT);
2394
487
  case NDPI_TLS_SELFSIGNED_CERTIFICATE:
2395
487
    return STRINGIFY(NDPI_TLS_SELFSIGNED_CERTIFICATE);
2396
472
  case NDPI_TLS_OBSOLETE_VERSION:
2397
472
    return STRINGIFY(NDPI_TLS_OBSOLETE_VERSION);
2398
480
  case NDPI_TLS_WEAK_CIPHER:
2399
480
    return STRINGIFY(NDPI_TLS_WEAK_CIPHER);
2400
479
  case NDPI_TLS_CERTIFICATE_EXPIRED:
2401
479
    return STRINGIFY(NDPI_TLS_CERTIFICATE_EXPIRED);
2402
491
  case NDPI_TLS_CERTIFICATE_MISMATCH:
2403
491
    return STRINGIFY(NDPI_TLS_CERTIFICATE_MISMATCH);
2404
478
  case NDPI_HTTP_SUSPICIOUS_USER_AGENT:
2405
478
    return STRINGIFY(NDPI_HTTP_SUSPICIOUS_USER_AGENT);
2406
474
  case NDPI_NUMERIC_IP_HOST:
2407
474
    return STRINGIFY(NDPI_NUMERIC_IP_HOST);
2408
483
  case NDPI_HTTP_SUSPICIOUS_URL:
2409
483
    return STRINGIFY(NDPI_HTTP_SUSPICIOUS_URL);
2410
474
  case NDPI_HTTP_SUSPICIOUS_HEADER:
2411
474
    return STRINGIFY(NDPI_HTTP_SUSPICIOUS_HEADER);
2412
486
  case NDPI_TLS_NOT_CARRYING_HTTPS:
2413
486
    return STRINGIFY(NDPI_TLS_NOT_CARRYING_HTTPS);
2414
477
  case NDPI_SUSPICIOUS_DGA_DOMAIN:
2415
477
    return STRINGIFY(NDPI_SUSPICIOUS_DGA_DOMAIN);
2416
474
  case NDPI_MALFORMED_PACKET:
2417
474
    return STRINGIFY(NDPI_MALFORMED_PACKET);
2418
486
  case NDPI_SSH_OBSOLETE_CLIENT_VERSION_OR_CIPHER:
2419
486
    return STRINGIFY(NDPI_SSH_OBSOLETE_CLIENT_VERSION_OR_CIPHER);
2420
570
  case NDPI_SSH_OBSOLETE_SERVER_VERSION_OR_CIPHER:
2421
570
    return STRINGIFY(NDPI_SSH_OBSOLETE_SERVER_VERSION_OR_CIPHER);
2422
496
  case NDPI_SMB_INSECURE_VERSION:
2423
496
    return STRINGIFY(NDPI_SMB_INSECURE_VERSION);
2424
473
  case NDPI_MISMATCHING_PROTOCOL_WITH_IP:
2425
473
    return STRINGIFY(NDPI_MISMATCHING_PROTOCOL_WITH_IP);
2426
473
  case NDPI_UNSAFE_PROTOCOL:
2427
473
    return STRINGIFY(NDPI_TLS_SUSPICIOUS_ESNI_USAGE);
2428
477
  case NDPI_DNS_SUSPICIOUS_TRAFFIC:
2429
477
    return STRINGIFY(NDPI_DNS_SUSPICIOUS_TRAFFIC);
2430
478
  case NDPI_TLS_MISSING_SNI:
2431
478
    return STRINGIFY(NDPI_TLS_MISSING_SNI);
2432
477
  case NDPI_HTTP_SUSPICIOUS_CONTENT:
2433
477
    return STRINGIFY(NDPI_HTTP_SUSPICIOUS_CONTENT);
2434
474
  case NDPI_RISKY_ASN:
2435
474
    return STRINGIFY(NDPI_RISKY_ASN);
2436
470
  case NDPI_RISKY_DOMAIN:
2437
470
    return STRINGIFY(NDPI_RISKY_DOMAIN);
2438
476
  case NDPI_MALICIOUS_FINGERPRINT:
2439
476
    return STRINGIFY(NDPI_MALICIOUS_FINGERPRINT);
2440
472
  case NDPI_MALICIOUS_SHA1_CERTIFICATE:
2441
472
    return STRINGIFY(NDPI_MALICIOUS_SHA1_CERTIFICATE);
2442
471
  case NDPI_DESKTOP_OR_FILE_SHARING_SESSION:
2443
471
    return STRINGIFY(NDPI_DESKTOP_OR_FILE_SHARING_SESSION);
2444
474
  case NDPI_TLS_UNCOMMON_ALPN:
2445
474
    return STRINGIFY(NDPI_TLS_UNCOMMON_ALPN);
2446
484
  case NDPI_TLS_CERT_VALIDITY_TOO_LONG:
2447
484
    return STRINGIFY(NDPI_TLS_CERT_VALIDITY_TOO_LONG);
2448
470
  case NDPI_TLS_SUSPICIOUS_EXTENSION:
2449
470
    return STRINGIFY(NDPI_TLS_SUSPICIOUS_EXTENSION);
2450
486
  case NDPI_TLS_FATAL_ALERT:
2451
486
    return STRINGIFY(NDPI_TLS_FATAL_ALERT);
2452
473
  case NDPI_SUSPICIOUS_ENTROPY:
2453
473
    return STRINGIFY(NDPI_SUSPICIOUS_ENTROPY);
2454
474
  case NDPI_CLEAR_TEXT_CREDENTIALS:
2455
474
    return STRINGIFY(NDPI_CLEAR_TEXT_CREDENTIALS);
2456
474
  case NDPI_DNS_LARGE_PACKET:
2457
474
    return STRINGIFY(NDPI_DNS_LARGE_PACKET);
2458
479
  case NDPI_DNS_FRAGMENTED:
2459
479
    return STRINGIFY(NDPI_DNS_FRAGMENTED);
2460
471
  case NDPI_INVALID_CHARACTERS:
2461
471
    return STRINGIFY(NDPI_INVALID_CHARACTERS);
2462
479
  case NDPI_POSSIBLE_EXPLOIT:
2463
479
    return STRINGIFY(NDPI_POSSIBLE_EXPLOIT);
2464
472
  case NDPI_TLS_CERTIFICATE_ABOUT_TO_EXPIRE:
2465
472
    return STRINGIFY(NDPI_TLS_CERTIFICATE_ABOUT_TO_EXPIRE);
2466
480
  case NDPI_PUNYCODE_IDN:
2467
480
    return STRINGIFY(NDPI_PUNYCODE_IDN);
2468
481
  case NDPI_ERROR_CODE_DETECTED:
2469
481
    return STRINGIFY(NDPI_ERROR_CODE_DETECTED);
2470
480
  case NDPI_HTTP_CRAWLER_BOT:
2471
480
    return STRINGIFY(NDPI_HTTP_CRAWLER_BOT);
2472
475
  case NDPI_ANONYMOUS_SUBSCRIBER:
2473
475
    return STRINGIFY(NDPI_ANONYMOUS_SUBSCRIBER);
2474
479
  case NDPI_UNIDIRECTIONAL_TRAFFIC:
2475
479
    return STRINGIFY(NDPI_UNIDIRECTIONAL_TRAFFIC);
2476
481
  case NDPI_HTTP_OBSOLETE_SERVER:
2477
481
    return STRINGIFY(NDPI_HTTP_OBSOLETE_SERVER);
2478
477
  case NDPI_PERIODIC_FLOW:
2479
477
    return STRINGIFY(NDPI_PERIODIC_FLOW);
2480
479
  case NDPI_MINOR_ISSUES:
2481
479
    return STRINGIFY(NDPI_MINOR_ISSUES);
2482
472
  case NDPI_TCP_ISSUES:
2483
472
    return STRINGIFY(NDPI_MINOR_ISSUES);
2484
486
  case NDPI_UNRESOLVED_HOSTNAME:
2485
486
    return STRINGIFY(NDPI_UNRESOLVED_HOSTNAME);
2486
481
  case NDPI_TLS_ALPN_SNI_MISMATCH:
2487
481
    return STRINGIFY(NDPI_TLS_ALPN_SNI_MISMATCH);
2488
476
  case NDPI_MALWARE_HOST_CONTACTED:
2489
476
    return STRINGIFY(NDPI_MALWARE_HOST_CONTACTED);
2490
486
  case NDPI_BINARY_DATA_TRANSFER:
2491
486
    return STRINGIFY(NDPI_BINARY_DATA_TRANSFER);
2492
474
  case NDPI_PROBING_ATTEMPT:
2493
474
    return STRINGIFY(NDPI_PROBING_ATTEMPT);
2494
481
  case NDPI_OBFUSCATED_TRAFFIC:
2495
481
    return STRINGIFY(NDPI_OBFUSCATED_TRAFFIC);
2496
2497
644
  default:
2498
644
    return("Unknown risk");
2499
27.8k
  }
2500
27.8k
}
2501
2502
/* ******************************************************************** */
2503
2504
765
ndpi_risk_enum ndpi_code2risk(const char* risk) {
2505
765
  if(strcmp(STRINGIFY(NDPI_NO_RISK), risk) == 0)
2506
208
    return(NDPI_NO_RISK);
2507
557
  else if(strcmp(STRINGIFY(NDPI_URL_POSSIBLE_XSS), risk) == 0)
2508
7
    return(NDPI_URL_POSSIBLE_XSS);
2509
550
  else if(strcmp(STRINGIFY(NDPI_URL_POSSIBLE_SQL_INJECTION), risk) == 0)
2510
8
    return(NDPI_URL_POSSIBLE_SQL_INJECTION);
2511
542
  else if(strcmp(STRINGIFY(NDPI_URL_POSSIBLE_RCE_INJECTION), risk) == 0)
2512
8
    return(NDPI_URL_POSSIBLE_RCE_INJECTION);
2513
534
  else if(strcmp(STRINGIFY(NDPI_BINARY_APPLICATION_TRANSFER), risk) == 0)
2514
16
    return(NDPI_BINARY_APPLICATION_TRANSFER);
2515
518
  else if(strcmp(STRINGIFY(NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT), risk) == 0)
2516
5
    return(NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT);
2517
513
  else if(strcmp(STRINGIFY(NDPI_TLS_SELFSIGNED_CERTIFICATE), risk) == 0)
2518
16
    return(NDPI_TLS_SELFSIGNED_CERTIFICATE);
2519
497
  else if(strcmp(STRINGIFY(NDPI_TLS_OBSOLETE_VERSION), risk) == 0)
2520
2
    return(NDPI_TLS_OBSOLETE_VERSION);
2521
495
  else if(strcmp(STRINGIFY(NDPI_TLS_WEAK_CIPHER), risk) == 0)
2522
9
    return(NDPI_TLS_WEAK_CIPHER);
2523
486
  else if(strcmp(STRINGIFY(NDPI_TLS_CERTIFICATE_EXPIRED), risk) == 0)
2524
8
    return(NDPI_TLS_CERTIFICATE_EXPIRED);
2525
478
  else if(strcmp(STRINGIFY(NDPI_TLS_CERTIFICATE_MISMATCH), risk) == 0)
2526
21
    return(NDPI_TLS_CERTIFICATE_MISMATCH);
2527
457
  else if(strcmp(STRINGIFY(NDPI_HTTP_SUSPICIOUS_USER_AGENT), risk) == 0)
2528
8
    return(NDPI_HTTP_SUSPICIOUS_USER_AGENT);
2529
449
  else if(strcmp(STRINGIFY(NDPI_NUMERIC_IP_HOST), risk) == 0)
2530
4
    return(NDPI_NUMERIC_IP_HOST);
2531
445
  else if(strcmp(STRINGIFY(NDPI_HTTP_SUSPICIOUS_URL), risk) == 0)
2532
13
    return(NDPI_HTTP_SUSPICIOUS_URL);
2533
432
  else if(strcmp(STRINGIFY(NDPI_HTTP_SUSPICIOUS_HEADER), risk) == 0)
2534
4
    return(NDPI_HTTP_SUSPICIOUS_HEADER);
2535
428
  else if(strcmp(STRINGIFY(NDPI_TLS_NOT_CARRYING_HTTPS), risk) == 0)
2536
15
    return(NDPI_TLS_NOT_CARRYING_HTTPS);
2537
413
  else if(strcmp(STRINGIFY(NDPI_SUSPICIOUS_DGA_DOMAIN), risk) == 0)
2538
4
    return(NDPI_SUSPICIOUS_DGA_DOMAIN);
2539
409
  else if(strcmp(STRINGIFY(NDPI_MALFORMED_PACKET), risk) == 0)
2540
4
    return(NDPI_MALFORMED_PACKET);
2541
405
  else if(strcmp(STRINGIFY(NDPI_SSH_OBSOLETE_CLIENT_VERSION_OR_CIPHER), risk) == 0)
2542
16
    return(NDPI_SSH_OBSOLETE_CLIENT_VERSION_OR_CIPHER);
2543
389
  else if(strcmp(STRINGIFY(NDPI_SSH_OBSOLETE_SERVER_VERSION_OR_CIPHER), risk) == 0)
2544
100
    return(NDPI_SSH_OBSOLETE_SERVER_VERSION_OR_CIPHER);
2545
289
  else if(strcmp(STRINGIFY(NDPI_SMB_INSECURE_VERSION), risk) == 0)
2546
26
    return(NDPI_SMB_INSECURE_VERSION);
2547
263
  else if(strcmp(STRINGIFY(NDPI_MISMATCHING_PROTOCOL_WITH_IP), risk) == 0)
2548
3
    return(NDPI_MISMATCHING_PROTOCOL_WITH_IP);
2549
260
  else if(strcmp(STRINGIFY(NDPI_UNSAFE_PROTOCOL), risk) == 0)
2550
0
    return(NDPI_UNSAFE_PROTOCOL);
2551
260
  else if(strcmp(STRINGIFY(NDPI_DNS_SUSPICIOUS_TRAFFIC), risk) == 0)
2552
7
    return(NDPI_DNS_SUSPICIOUS_TRAFFIC);
2553
253
  else if(strcmp(STRINGIFY(NDPI_TLS_MISSING_SNI), risk) == 0)
2554
7
    return(NDPI_TLS_MISSING_SNI);
2555
246
  else if(strcmp(STRINGIFY(NDPI_HTTP_SUSPICIOUS_CONTENT), risk) == 0)
2556
7
    return(NDPI_HTTP_SUSPICIOUS_CONTENT);
2557
239
  else if(strcmp(STRINGIFY(NDPI_RISKY_ASN), risk) == 0)
2558
4
    return(NDPI_RISKY_ASN);
2559
235
  else if(strcmp(STRINGIFY(NDPI_RISKY_DOMAIN), risk) == 0)
2560
0
    return(NDPI_RISKY_DOMAIN);
2561
235
  else if(strcmp(STRINGIFY(NDPI_MALICIOUS_FINGERPRINT), risk) == 0)
2562
6
    return(NDPI_MALICIOUS_FINGERPRINT);
2563
229
  else if(strcmp(STRINGIFY(NDPI_MALICIOUS_SHA1_CERTIFICATE), risk) == 0)
2564
2
    return(NDPI_MALICIOUS_SHA1_CERTIFICATE);
2565
227
  else if(strcmp(STRINGIFY(NDPI_DESKTOP_OR_FILE_SHARING_SESSION), risk) == 0)
2566
1
    return(NDPI_DESKTOP_OR_FILE_SHARING_SESSION);
2567
226
  else if(strcmp(STRINGIFY(NDPI_TLS_UNCOMMON_ALPN), risk) == 0)
2568
4
    return(NDPI_TLS_UNCOMMON_ALPN);
2569
222
  else if(strcmp(STRINGIFY(NDPI_TLS_CERT_VALIDITY_TOO_LONG), risk) == 0)
2570
14
    return(NDPI_TLS_CERT_VALIDITY_TOO_LONG);
2571
208
  else if(strcmp(STRINGIFY(NDPI_TLS_SUSPICIOUS_EXTENSION), risk) == 0)
2572
0
    return(NDPI_TLS_SUSPICIOUS_EXTENSION);
2573
208
  else if(strcmp(STRINGIFY(NDPI_TLS_FATAL_ALERT), risk) == 0)
2574
16
    return(NDPI_TLS_FATAL_ALERT);
2575
192
  else if(strcmp(STRINGIFY(NDPI_SUSPICIOUS_ENTROPY), risk) == 0)
2576
3
    return(NDPI_SUSPICIOUS_ENTROPY);
2577
189
  else if(strcmp(STRINGIFY(NDPI_CLEAR_TEXT_CREDENTIALS), risk) == 0)
2578
4
    return(NDPI_CLEAR_TEXT_CREDENTIALS);
2579
185
  else if(strcmp(STRINGIFY(NDPI_DNS_LARGE_PACKET), risk) == 0)
2580
4
    return(NDPI_DNS_LARGE_PACKET);
2581
181
  else if(strcmp(STRINGIFY(NDPI_DNS_FRAGMENTED), risk) == 0)
2582
9
    return(NDPI_DNS_FRAGMENTED);
2583
172
  else if(strcmp(STRINGIFY(NDPI_INVALID_CHARACTERS), risk) == 0)
2584
1
    return(NDPI_INVALID_CHARACTERS);
2585
171
  else if(strcmp(STRINGIFY(NDPI_POSSIBLE_EXPLOIT), risk) == 0)
2586
9
    return(NDPI_POSSIBLE_EXPLOIT);
2587
162
  else if(strcmp(STRINGIFY(NDPI_TLS_CERTIFICATE_ABOUT_TO_EXPIRE), risk) == 0)
2588
1
    return(NDPI_TLS_CERTIFICATE_ABOUT_TO_EXPIRE);
2589
161
  else if(strcmp(STRINGIFY(NDPI_PUNYCODE_IDN), risk) == 0)
2590
10
    return(NDPI_PUNYCODE_IDN);
2591
151
  else if(strcmp(STRINGIFY(NDPI_ERROR_CODE_DETECTED), risk) == 0)
2592
11
    return(NDPI_ERROR_CODE_DETECTED);
2593
140
  else if(strcmp(STRINGIFY(NDPI_HTTP_CRAWLER_BOT), risk) == 0)
2594
10
    return(NDPI_HTTP_CRAWLER_BOT);
2595
130
  else if(strcmp(STRINGIFY(NDPI_ANONYMOUS_SUBSCRIBER), risk) == 0)
2596
4
    return(NDPI_ANONYMOUS_SUBSCRIBER);
2597
126
  else if(strcmp(STRINGIFY(NDPI_UNIDIRECTIONAL_TRAFFIC), risk) == 0)
2598
9
    return(NDPI_UNIDIRECTIONAL_TRAFFIC);
2599
117
  else if(strcmp(STRINGIFY(NDPI_HTTP_OBSOLETE_SERVER), risk) == 0)
2600
10
    return(NDPI_HTTP_OBSOLETE_SERVER);
2601
107
  else if(strcmp(STRINGIFY(NDPI_PERIODIC_FLOW), risk) == 0)
2602
7
    return(NDPI_PERIODIC_FLOW);
2603
100
  else if(strcmp(STRINGIFY(NDPI_MINOR_ISSUES), risk) == 0)
2604
11
    return(NDPI_MINOR_ISSUES);
2605
89
  else if(strcmp(STRINGIFY(NDPI_TCP_ISSUES), risk) == 0)
2606
0
    return(NDPI_MINOR_ISSUES);
2607
89
  else if(strcmp(STRINGIFY(NDPI_UNRESOLVED_HOSTNAME), risk) == 0)
2608
16
    return(NDPI_UNRESOLVED_HOSTNAME);
2609
73
  else if(strcmp(STRINGIFY(NDPI_TLS_ALPN_SNI_MISMATCH), risk) == 0)
2610
11
    return(NDPI_TLS_ALPN_SNI_MISMATCH);
2611
62
  else if(strcmp(STRINGIFY(NDPI_MALWARE_HOST_CONTACTED), risk) == 0)
2612
5
    return(NDPI_MALWARE_HOST_CONTACTED);
2613
57
  else if(strcmp(STRINGIFY(NDPI_BINARY_DATA_TRANSFER), risk) == 0)
2614
16
    return(NDPI_BINARY_DATA_TRANSFER);
2615
41
  else if(strcmp(STRINGIFY(NDPI_PROBING_ATTEMPT), risk) == 0)
2616
4
    return(NDPI_PROBING_ATTEMPT);
2617
37
  else if(strcmp(STRINGIFY(NDPI_OBFUSCATED_TRAFFIC), risk) == 0)
2618
11
    return(NDPI_OBFUSCATED_TRAFFIC);
2619
26
  else
2620
26
    return(NDPI_MAX_RISK);
2621
765
}
2622
2623
/* ******************************************************************** */
2624
2625
27.0k
const char* ndpi_severity2str(ndpi_risk_severity s) {
2626
27.0k
  switch(s) {
2627
6.30k
  case NDPI_RISK_LOW:
2628
6.30k
    return("Low");
2629
2630
8.93k
  case NDPI_RISK_MEDIUM:
2631
8.93k
    return("Medium");
2632
2633
8.46k
  case NDPI_RISK_HIGH:
2634
8.46k
    return("High");
2635
2636
2.82k
  case NDPI_RISK_SEVERE:
2637
2.82k
    return("Severe");
2638
2639
2
  case NDPI_RISK_CRITICAL:
2640
2
    return("Critical");
2641
2642
3
  case NDPI_RISK_EMERGENCY:
2643
3
    return("Emergency");
2644
27.0k
  }
2645
2646
553
  return("");
2647
27.0k
}
2648
2649
/* ******************************************************************** */
2650
2651
u_int16_t ndpi_risk2score(ndpi_risk risk,
2652
        u_int16_t *client_score,
2653
27.8k
        u_int16_t *server_score) {
2654
27.8k
  u_int16_t score = 0;
2655
27.8k
  u_int32_t i;
2656
2657
27.8k
  *client_score = *server_score = 0; /* Reset values */
2658
2659
27.8k
  if(risk == 0) return(0);
2660
2661
1.59M
  for(i = 0; i < NDPI_MAX_RISK; i++) {
2662
1.56M
    ndpi_risk_enum r = (ndpi_risk_enum)i;
2663
2664
1.56M
    if(NDPI_ISSET_BIT(risk, r)) {
2665
37.2k
      ndpi_risk_info *info = ndpi_risk2severity(r);
2666
37.2k
      u_int16_t val = 0, client_score_val;
2667
2668
37.2k
      switch(info->severity) {
2669
8.07k
      case NDPI_RISK_LOW:
2670
8.07k
  val = NDPI_SCORE_RISK_LOW;
2671
8.07k
  break;
2672
2673
11.4k
      case NDPI_RISK_MEDIUM:
2674
11.4k
  val = NDPI_SCORE_RISK_MEDIUM;
2675
11.4k
  break;
2676
2677
12.5k
      case NDPI_RISK_HIGH:
2678
12.5k
  val = NDPI_SCORE_RISK_HIGH;
2679
12.5k
  break;
2680
2681
5.11k
      case NDPI_RISK_SEVERE:
2682
5.11k
  val = NDPI_SCORE_RISK_SEVERE;
2683
5.11k
  break;
2684
2685
0
      case NDPI_RISK_CRITICAL:
2686
0
  val = NDPI_SCORE_RISK_CRITICAL;
2687
0
  break;
2688
2689
0
      case NDPI_RISK_EMERGENCY:
2690
0
  val = NDPI_SCORE_RISK_EMERGENCY;
2691
0
  break;
2692
37.2k
      }
2693
2694
37.2k
      score += val;
2695
37.2k
      client_score_val = (val * info->default_client_risk_pctg) / 100;
2696
2697
37.2k
      *client_score += client_score_val, *server_score += (val - client_score_val);
2698
37.2k
    }
2699
1.56M
  }
2700
2701
27.5k
  return(score);
2702
27.5k
}
2703
2704
const char *ndpi_risk_shortnames[NDPI_MAX_RISK] = {
2705
  "unknown",                    /* NDPI_NO_RISK */
2706
  "xss",
2707
  "sql",
2708
  "rce",
2709
  "binary_transfer",
2710
  "non_standard_port",
2711
  "tls_selfsigned_cert",
2712
  "tls_obsolete_ver",
2713
  "tls_weak_cipher",
2714
  "tls_cert_expired",
2715
  "tls_cert_mismatch",          /* NDPI_TLS_CERTIFICATE_MISMATCH */
2716
  "http_susp_ua",
2717
  "numeric_ip_host",
2718
  "http_susp_url",
2719
  "http_susp_header",
2720
  "tls_not_https",
2721
  "dga",
2722
  "malformed_pkt",
2723
  "ssh_obsolete_client",
2724
  "ssh_obsolete_server",
2725
  "smb_insecure_ver",           /* NDPI_SMB_INSECURE_VERSION */
2726
  "mismatching_hostname_with_ip",
2727
  "unsafe_proto",
2728
  "dns_susp",
2729
  "tls_no_sni",
2730
  "http_susp_content",
2731
  "risky_asn",
2732
  "risky_domain",
2733
  "malicious_fingerprint",
2734
  "malicious_cert",
2735
  "desktop_sharing",            /* NDPI_DESKTOP_OR_FILE_SHARING_SESSION */
2736
  "uls_uncommon_alpn",
2737
  "tls_cert_too_long",
2738
  "tls_susp_ext",
2739
  "tls_fatal_err",
2740
  "susp_entropy",
2741
  "clear_credential",
2742
  "dns_large_pkt",
2743
  "dns_fragmented",
2744
  "invalid_characters",
2745
  "exploit",                    /* NDPI_POSSIBLE_EXPLOIT */
2746
  "tls_cert_about_to_expire",
2747
  "punycode",
2748
  "error_code",
2749
  "crawler_bot",
2750
  "anonymous_subscriber",
2751
  "unidirectional",
2752
  "http_obsolete_server",
2753
  "periodic_flow",
2754
  "minor_issues",
2755
  "tcp_issues",                 /* NDPI_TCP_ISSUES */
2756
  "unresolved_hostname",
2757
  "tls_alpn_mismatch",
2758
  "malware_host",
2759
  "binary_data_transfer",
2760
  "probing",
2761
  "obfuscated",
2762
};
2763
2764
/* ******************************************************************** */
2765
2766
1.53k
const char* ndpi_http_method2str(ndpi_http_method m) {
2767
1.53k
  switch(m) {
2768
856
  case NDPI_HTTP_METHOD_UNKNOWN:      break;
2769
8
  case NDPI_HTTP_METHOD_OPTIONS:      return("OPTIONS");
2770
148
  case NDPI_HTTP_METHOD_GET:          return("GET");
2771
2
  case NDPI_HTTP_METHOD_HEAD:         return("HEAD");
2772
0
  case NDPI_HTTP_METHOD_PATCH:        return("PATCH");
2773
2
  case NDPI_HTTP_METHOD_POST:         return("POST");
2774
7
  case NDPI_HTTP_METHOD_PUT:          return("PUT");
2775
1
  case NDPI_HTTP_METHOD_DELETE:       return("DELETE");
2776
6
  case NDPI_HTTP_METHOD_TRACE:        return("TRACE");
2777
1
  case NDPI_HTTP_METHOD_CONNECT:      return("CONNECT");
2778
8
  case NDPI_HTTP_METHOD_RPC_CONNECT:  return("RPC_CONNECT");
2779
0
  case NDPI_HTTP_METHOD_RPC_IN_DATA:  return("RPC_IN_DATA");
2780
0
  case NDPI_HTTP_METHOD_RPC_OUT_DATA: return("RPC_OUT_DATA");
2781
7
  case NDPI_HTTP_METHOD_MKCOL:        return("MKCOL");
2782
4
  case NDPI_HTTP_METHOD_MOVE:         return("MOVE");
2783
1
  case NDPI_HTTP_METHOD_COPY:         return("COPY");
2784
4
  case NDPI_HTTP_METHOD_LOCK:         return("LOCK");
2785
1
  case NDPI_HTTP_METHOD_UNLOCK:       return("UNLOCK");
2786
1
  case NDPI_HTTP_METHOD_PROPFIND:     return("PROPFIND");
2787
1
  case NDPI_HTTP_METHOD_PROPPATCH:    return("PROPPATCH");
2788
1.53k
  }
2789
2790
1.32k
  return("Unknown HTTP method");
2791
1.53k
}
2792
2793
/* ******************************************************************** */
2794
2795
141
ndpi_http_method ndpi_http_str2method(const char* method, u_int16_t method_len) {
2796
141
  if(!method || method_len < 3)
2797
0
    return(NDPI_HTTP_METHOD_UNKNOWN);
2798
2799
141
  switch(method[0]) {
2800
0
  case 'O': return(NDPI_HTTP_METHOD_OPTIONS);
2801
140
  case 'G': return(NDPI_HTTP_METHOD_GET);
2802
0
  case 'H': return(NDPI_HTTP_METHOD_HEAD);
2803
0
  case 'L': return(NDPI_HTTP_METHOD_LOCK);
2804
2805
0
  case 'M':
2806
0
    if (method[1] == 'O')
2807
0
      return(NDPI_HTTP_METHOD_MOVE);
2808
0
    else
2809
0
      return(NDPI_HTTP_METHOD_MKCOL);
2810
2811
1
  case 'P':
2812
1
    switch(method[1]) {
2813
0
    case 'A':return(NDPI_HTTP_METHOD_PATCH);
2814
1
    case 'O':return(NDPI_HTTP_METHOD_POST);
2815
0
    case 'U':return(NDPI_HTTP_METHOD_PUT);
2816
0
    case 'R':
2817
0
      if (method_len >= 5) {
2818
0
        if (strncmp(method, "PROPF", 5) == 0)
2819
0
          return(NDPI_HTTP_METHOD_PROPFIND);
2820
0
        else if (strncmp(method, "PROPP", 5) == 0)
2821
0
          return NDPI_HTTP_METHOD_PROPPATCH;
2822
0
      }
2823
1
    }
2824
0
    break;
2825
2826
0
  case 'D':  return(NDPI_HTTP_METHOD_DELETE);
2827
0
  case 'T':  return(NDPI_HTTP_METHOD_TRACE);
2828
0
  case 'C':
2829
0
    if (method_len == 4)
2830
0
      return(NDPI_HTTP_METHOD_COPY);
2831
0
    else
2832
0
      return(NDPI_HTTP_METHOD_CONNECT);
2833
2834
0
  case 'R':
2835
0
    if(method_len >= 11) {
2836
0
      if(strncmp(method, "RPC_CONNECT", 11) == 0) {
2837
0
        return(NDPI_HTTP_METHOD_RPC_CONNECT);
2838
0
      } else if(strncmp(method, "RPC_IN_DATA", 11) == 0) {
2839
0
        return(NDPI_HTTP_METHOD_RPC_IN_DATA);
2840
0
      } else if(strncmp(method, "RPC_OUT_DATA", 11) == 0) {
2841
0
        return(NDPI_HTTP_METHOD_RPC_OUT_DATA);
2842
0
      }
2843
0
    }
2844
0
    break;
2845
2846
0
  case 'U': return(NDPI_HTTP_METHOD_UNLOCK);
2847
141
  }
2848
2849
0
  return(NDPI_HTTP_METHOD_UNKNOWN);
2850
141
}
2851
2852
/* ******************************************************************** */
2853
2854
4.48k
int ndpi_hash_init(ndpi_str_hash **h) {
2855
4.48k
  if (h == NULL)
2856
0
    return 1;
2857
2858
4.48k
  *h = ndpi_calloc(1, sizeof(**h));
2859
4.48k
  if(!*h)
2860
44
    return 1;
2861
4.43k
  return 0;
2862
4.48k
}
2863
2864
/* ******************************************************************** */
2865
2866
4.43k
void ndpi_hash_free(ndpi_str_hash **h) {
2867
4.43k
  if(h && *h) {
2868
4.43k
    ndpi_str_hash_priv *h_priv = (ndpi_str_hash_priv *)((*h)->priv);
2869
4.43k
    ndpi_str_hash_priv *current, *tmp;
2870
2871
3.22M
    HASH_ITER(hh, h_priv, current, tmp) {
2872
3.22M
      HASH_DEL(h_priv, current);
2873
3.22M
      ndpi_free(current->key);
2874
3.22M
      ndpi_free(current);
2875
3.22M
    }
2876
2877
4.43k
    ndpi_free(*h);
2878
4.43k
    *h = NULL;
2879
4.43k
  }
2880
4.43k
}
2881
2882
/* ******************************************************************** */
2883
2884
103k
int ndpi_hash_find_entry(ndpi_str_hash *h, char *key, u_int key_len, u_int64_t *value) {
2885
103k
  ndpi_str_hash_priv *h_priv;
2886
103k
  ndpi_str_hash_priv *item;
2887
2888
103k
  if(!h || !key || key_len == 0)
2889
2.81k
    return(2);
2890
2891
100k
  h_priv = (ndpi_str_hash_priv *)((h)->priv);
2892
2893
100k
  h->stats.n_search++;
2894
100k
  HASH_FIND(hh, h_priv, key, key_len, item);
2895
2896
100k
  if (item != NULL) {
2897
44.1k
    if(value != NULL)
2898
44.1k
      *value = item->value64;
2899
2900
44.1k
    h->stats.n_found++;
2901
44.1k
    return 0;
2902
44.1k
  } else
2903
56.2k
    return 1;
2904
100k
}
2905
2906
/* ******************************************************************** */
2907
2908
3.29M
int ndpi_hash_add_entry(ndpi_str_hash **h, char *key, u_int8_t key_len, u_int64_t value) {
2909
3.29M
  ndpi_str_hash_priv *h_priv;
2910
3.29M
  ndpi_str_hash_priv *item, *ret_found;
2911
2912
3.29M
  if(!h || !*h || !key || key_len == 0)
2913
0
    return(3);
2914
2915
3.29M
  h_priv = (ndpi_str_hash_priv *)((*h)->priv);
2916
2917
3.29M
  HASH_FIND(hh, h_priv, key, key_len, item);
2918
2919
3.29M
  if(item != NULL) {
2920
0
    item->value64 = value;
2921
0
    return(1); /* Entry already present */
2922
0
  }
2923
2924
3.29M
  item = ndpi_calloc(1, sizeof(ndpi_str_hash_priv));
2925
3.29M
  if(item == NULL)
2926
37.9k
    return(2);
2927
2928
3.25M
  item->key = ndpi_malloc(key_len+1);
2929
2930
3.25M
  if(item->key == NULL) {
2931
36.2k
    ndpi_free(item);
2932
36.2k
    return(1);
2933
3.22M
  } else {
2934
3.22M
    memcpy(item->key, key, key_len);
2935
3.22M
    item->key[key_len] = '\0';
2936
3.22M
  }
2937
2938
3.22M
  item->value64 = value;
2939
2940
3.22M
  HASH_ADD(hh, *(ndpi_str_hash_priv **)&((*h)->priv), key[0], key_len, item);
2941
2942
3.22M
  HASH_FIND(hh, *(ndpi_str_hash_priv **)&((*h)->priv), key, key_len, ret_found);
2943
3.22M
  if(ret_found == NULL) { /* The insertion failed (because of a memory allocation error) */
2944
85
    ndpi_free(item->key);
2945
85
    ndpi_free(item);
2946
85
    return 4;
2947
85
  }
2948
2949
3.22M
  return 0;
2950
3.22M
}
2951
2952
/* ******************************************************************** */
2953
2954
5.01k
void ndpi_hash_get_stats(ndpi_str_hash *h, struct ndpi_str_hash_stats *stats) {
2955
5.01k
  if(h) {
2956
1.63k
    stats->n_search = h->stats.n_search;
2957
1.63k
    stats->n_found = h->stats.n_found;
2958
3.37k
  } else {
2959
3.37k
    stats->n_search = 0;
2960
3.37k
    stats->n_found = 0;
2961
3.37k
  }
2962
5.01k
}
2963
2964
/* ******************************************************************** */
2965
2966
0
void ndpi_hash_walk(ndpi_str_hash **h, ndpi_hash_walk_iter cb, void *data) {
2967
0
  if(h && *h) {
2968
0
    ndpi_str_hash_priv *h_priv = (ndpi_str_hash_priv *)((*h)->priv);
2969
0
    ndpi_str_hash_priv *current, *tmp;
2970
2971
0
    HASH_ITER(hh, h_priv, current, tmp) {
2972
0
      cb(current->key, current->value64, data);
2973
0
    }
2974
0
  }
2975
0
}
2976
2977
/* ******************************************************************** */
2978
2979
int ndpi_get_hash_stats(struct ndpi_detection_module_struct *ndpi_struct,
2980
                        str_hash_type hash_type,
2981
                        struct ndpi_str_hash_stats *stats)
2982
6.12k
{
2983
6.12k
  if(!ndpi_struct || !stats)
2984
392
    return -1;
2985
2986
5.72k
  switch(hash_type) {
2987
716
  case NDPI_STR_HASH_MALICIOUS_JA4:
2988
716
    ndpi_hash_get_stats(ndpi_struct->malicious_ja4_hashmap, stats);
2989
716
    return 0;
2990
2991
716
  case NDPI_STR_HASH_MALICIOUS_SHA1:
2992
716
    ndpi_hash_get_stats(ndpi_struct->malicious_sha1_hashmap, stats);
2993
716
    return 0;
2994
2995
716
  case NDPI_STR_HASH_TCP_FINGERPRINTS:
2996
716
    ndpi_hash_get_stats(ndpi_struct->tcp_fingerprint_hashmap, stats);
2997
716
    return 0;
2998
2999
716
  case NDPI_STR_HASH_PUBLIC_DOMAIN_SUFFIX:
3000
716
    ndpi_hash_get_stats(ndpi_struct->public_domain_suffixes, stats);
3001
716
    return 0;
3002
3003
716
  case NDPI_STR_HASH_JA4_CUSTOM_PROTOS:
3004
716
    ndpi_hash_get_stats(ndpi_struct->ja4_custom_protos, stats);
3005
716
    return 0;
3006
3007
716
  case NDPI_STR_HASH_FP_CUSTOM_PROTOS:
3008
716
    ndpi_hash_get_stats(ndpi_struct->ndpifp_custom_protos, stats);
3009
716
    return 0;
3010
3011
716
  case NDPI_STR_HASH_HTTP_URL:
3012
716
    ndpi_hash_get_stats(ndpi_struct->http_url_hashmap, stats);
3013
716
    return 0;
3014
3015
716
  default:
3016
716
    return -1;
3017
5.72k
  }
3018
5.72k
}
3019
3020
/* ********************************************************************************* */
3021
3022
static u_int64_t ndpi_host_ip_risk_ptree_match(struct ndpi_detection_module_struct *ndpi_str,
3023
1.12k
                 struct in_addr *pin /* network byte order */) {
3024
1.12k
  ndpi_prefix_t prefix;
3025
1.12k
  ndpi_patricia_node_t *node;
3026
3027
1.12k
  if(!ndpi_str->ip_risk_mask)
3028
3
    return((u_int64_t)-1);
3029
3030
  /* Make sure all in network byte order otherwise compares wont work */
3031
1.12k
  ndpi_fill_prefix_v4(&prefix, pin, 32,
3032
1.12k
          ((ndpi_patricia_tree_t *) ndpi_str->ip_risk_mask->v4)->maxbits);
3033
1.12k
  node = ndpi_patricia_search_best(ndpi_str->ip_risk_mask->v4, &prefix);
3034
3035
1.12k
  if(node)
3036
0
    return(node->value.u.uv64);
3037
1.12k
  else
3038
1.12k
    return((u_int64_t)-1);
3039
1.12k
}
3040
3041
/* ********************************************************************************* */
3042
3043
static u_int64_t ndpi_host_ip_risk_ptree_match6(struct ndpi_detection_module_struct *ndpi_str,
3044
0
                  struct in6_addr *pin6) {
3045
0
  ndpi_prefix_t prefix;
3046
0
  ndpi_patricia_node_t *node;
3047
3048
0
  if(!ndpi_str->ip_risk_mask)
3049
0
    return((u_int64_t)-1);
3050
3051
  /* Make sure all in network byte order otherwise compares wont work */
3052
0
  ndpi_fill_prefix_v6(&prefix, pin6, 128,
3053
0
          ((ndpi_patricia_tree_t *) ndpi_str->ip_risk_mask->v6)->maxbits);
3054
0
  node = ndpi_patricia_search_best(ndpi_str->ip_risk_mask->v6, &prefix);
3055
3056
0
  if(node)
3057
0
    return(node->value.u.uv64);
3058
0
  else
3059
0
    return((u_int64_t)-1);
3060
0
}
3061
3062
/* ********************************************************************************* */
3063
3064
/* Check isuerDN exception */
3065
u_int8_t ndpi_check_issuerdn_risk_exception(struct ndpi_detection_module_struct *ndpi_str,
3066
704
              char *issuerDN) {
3067
704
  if(issuerDN != NULL) {
3068
704
    ndpi_list *head = ndpi_str->trusted_issuer_dn;
3069
3070
704
    while(head != NULL) {
3071
103
      if(strcmp(issuerDN, head->value) == 0)
3072
103
  return(1); /* This is a trusted DN */
3073
0
      else
3074
0
  head = head->next;
3075
103
    }
3076
704
  }
3077
3078
601
  return(0 /* no exception */);
3079
704
}
3080
3081
/* ********************************************************************************* */
3082
3083
/* Check host exception */
3084
static u_int8_t ndpi_check_hostname_risk_exception(struct ndpi_detection_module_struct *ndpi_str,
3085
               struct ndpi_flow_struct *flow,
3086
805
               char *hostname) {
3087
805
  if(hostname == NULL)
3088
0
    return(0);
3089
805
  else {
3090
805
    ndpi_automa *automa = &ndpi_str->host_risk_mask_automa;
3091
805
    u_int8_t ret = 0;
3092
3093
805
    if(automa && automa->ac_automa) {
3094
796
      AC_TEXT_t ac_input_text;
3095
796
      AC_REP_t match;
3096
3097
796
      memset(&match, 0, sizeof(match));
3098
796
      ac_input_text.astring = hostname, ac_input_text.length = strlen(hostname);
3099
796
      ac_input_text.option = 0;
3100
3101
796
      if(ac_automata_search(automa->ac_automa, &ac_input_text, &match) > 0) {
3102
0
  if(flow) flow->risk_mask &= match.number64;
3103
0
  ret = 1;
3104
0
      }
3105
796
    }
3106
3107
805
    return(ret);
3108
805
  }
3109
805
}
3110
3111
/* ********************************************************************************* */
3112
3113
/* Check host exception */
3114
static u_int8_t ndpi_check_ipv4_exception(struct ndpi_detection_module_struct *ndpi_str,
3115
            struct ndpi_flow_struct *flow,
3116
1.12k
            u_int32_t addr) {
3117
1.12k
  struct in_addr pin;
3118
1.12k
  u_int64_t r;
3119
3120
1.12k
  pin.s_addr = addr;
3121
1.12k
  r = ndpi_host_ip_risk_ptree_match(ndpi_str, &pin);
3122
3123
1.12k
  if(flow) flow->risk_mask &= r;
3124
3125
1.12k
  return((r != (u_int64_t)-1) ? 1 : 0);
3126
1.12k
}
3127
3128
/* ********************************************************************************* */
3129
3130
static u_int8_t ndpi_check_ipv6_exception(struct ndpi_detection_module_struct *ndpi_str,
3131
            struct ndpi_flow_struct *flow,
3132
0
            struct in6_addr *addr) {
3133
0
  u_int64_t r;
3134
3135
0
  r = ndpi_host_ip_risk_ptree_match6(ndpi_str, addr);
3136
3137
0
  if(flow) flow->risk_mask &= r;
3138
3139
0
  return((r != (u_int64_t)-1) ? 1 : 0);
3140
0
}
3141
3142
/* ********************************************************************************* */
3143
3144
int is_flowrisk_enabled(struct ndpi_detection_module_struct *ndpi_str, ndpi_risk_enum flowrisk_id)
3145
12.6k
{
3146
12.6k
  if(ndpi_bitmask_is_set(&ndpi_str->cfg.flowrisk_bitmask, flowrisk_id) == 0)
3147
45
    return 0;
3148
12.6k
  return 1;
3149
12.6k
}
3150
3151
/* ********************************************************************************* */
3152
3153
int is_flowrisk_info_enabled(struct ndpi_detection_module_struct *ndpi_str, ndpi_risk_enum flowrisk_id)
3154
12.5k
{
3155
12.5k
  if(ndpi_bitmask_is_set(&ndpi_str->cfg.flowrisk_info_bitmask, flowrisk_id) == 0)
3156
2
    return 0;
3157
12.5k
  return 1;
3158
12.5k
}
3159
3160
/* ********************************************************************************* */
3161
3162
void ndpi_handle_risk_exceptions(struct ndpi_detection_module_struct *ndpi_str,
3163
270
         struct ndpi_flow_struct *flow) {
3164
270
  if(flow->risk == 0) return; /* Nothing to do */
3165
3166
270
  if((!flow->host_risk_mask_evaluated) && (!flow->ip_risk_mask_evaluated))
3167
264
    flow->risk_mask = (u_int64_t)-1; /* No mask */
3168
3169
270
  if(!flow->host_risk_mask_evaluated) {
3170
268
    char *host = ndpi_get_flow_name(flow);
3171
3172
268
    if(host && (host[0] != '\0')) {
3173
      /* Check host exception */
3174
101
      ndpi_check_hostname_risk_exception(ndpi_str, flow, host);
3175
3176
101
      if(flow->risk_mask == 0) {
3177
0
  u_int i;
3178
3179
  /*
3180
    Might be that the exception applied when some risks
3181
    were already triggered: we need to clean them up
3182
  */
3183
0
  for(i=0; i<flow->num_risk_infos; i++) {
3184
0
    if(flow->risk_infos[i].info != NULL) {
3185
0
      ndpi_free(flow->risk_infos[i].info);
3186
0
      flow->risk_infos[i].info = NULL;
3187
0
    }
3188
3189
0
    flow->risk_infos[i].id = NDPI_NO_RISK;
3190
0
  }
3191
3192
0
  flow->num_risk_infos = 0;
3193
0
      }
3194
3195
      /* Used to avoid double checks (e.g. in DNS req/rsp) */
3196
101
      flow->host_risk_mask_evaluated = 1;
3197
101
    }
3198
268
  }
3199
3200
270
  if(!flow->ip_risk_mask_evaluated) {
3201
264
    if(flow->is_ipv6 == 0) {
3202
264
      ndpi_check_ipv4_exception(ndpi_str, flow, flow->c_address.v4 /* Client */);
3203
264
      ndpi_check_ipv4_exception(ndpi_str, flow, flow->s_address.v4 /* Server */);
3204
264
    } else {
3205
0
      ndpi_check_ipv6_exception(ndpi_str, flow, (struct in6_addr *)&flow->c_address.v6 /* Client */);
3206
0
      ndpi_check_ipv6_exception(ndpi_str, flow, (struct in6_addr *)&flow->s_address.v6 /* Server */);
3207
0
    }
3208
3209
264
    flow->ip_risk_mask_evaluated = 1;
3210
264
  }
3211
3212
270
  flow->risk &= flow->risk_mask;
3213
270
}
3214
3215
/* ******************************************************************** */
3216
3217
void ndpi_set_risk(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
3218
12.2k
                   ndpi_risk_enum r, char *risk_message) {
3219
12.2k
  if(!flow) return;
3220
3221
12.2k
  if(!is_flowrisk_enabled(ndpi_str, r))
3222
45
    return;
3223
3224
  /* Check if the risk is not yet set */
3225
12.1k
  if(!ndpi_isset_risk(flow, r)) {
3226
2.58k
    ndpi_risk v = 1ull << r;
3227
3228
    /* In case there is an exception set, take it into account */
3229
2.58k
    if(flow->host_risk_mask_evaluated)
3230
161
      v &= flow->risk_mask;
3231
3232
    // NDPI_SET_BIT(flow->risk, (u_int32_t)r);
3233
2.58k
    flow->risk |= v;
3234
3235
    /* Will be handled by ndpi_reconcile_protocols() */
3236
    // ndpi_handle_risk_exceptions(ndpi_str, flow);
3237
3238
2.58k
    if(flow->risk != 0 /* check if it has been masked */) {
3239
2.58k
      if(is_flowrisk_info_enabled(ndpi_str, r) &&
3240
2.58k
         risk_message != NULL) {
3241
2.58k
  if(flow->num_risk_infos < MAX_NUM_RISK_INFOS) {
3242
2.58k
    char *s = ndpi_strdup(risk_message);
3243
3244
2.58k
    if(s != NULL) {
3245
2.57k
      flow->risk_infos[flow->num_risk_infos].id = r;
3246
2.57k
      flow->risk_infos[flow->num_risk_infos].info = s;
3247
2.57k
      flow->num_risk_infos++;
3248
2.57k
    }
3249
2.58k
  }
3250
2.58k
      }
3251
2.58k
    }
3252
9.59k
  } else if(is_flowrisk_info_enabled(ndpi_str, r) && risk_message) {
3253
9.59k
    u_int8_t i;
3254
3255
34.5k
    for(i = 0; i < flow->num_risk_infos; i++)
3256
34.5k
      if(flow->risk_infos[i].id == r)
3257
9.59k
        return;
3258
3259
    /* Risk already set without any details, but now we have a specific risk_message
3260
       that we want to save.
3261
       This might happen with NDPI_HTTP_CRAWLER_BOT which might have been set early via
3262
       IP matching (no details) and now via UA matching (with message). */
3263
0
    if(flow->num_risk_infos < MAX_NUM_RISK_INFOS) {
3264
0
      char *s = ndpi_strdup(risk_message);
3265
3266
0
      if(s != NULL) {
3267
0
        flow->risk_infos[flow->num_risk_infos].id = r;
3268
0
        flow->risk_infos[flow->num_risk_infos].info = s;
3269
0
        flow->num_risk_infos++;
3270
0
      }
3271
0
    }
3272
0
  }
3273
12.1k
}
3274
3275
/* ******************************************************************** */
3276
3277
void ndpi_unset_risk(struct ndpi_detection_module_struct *ndpi_str,
3278
556
                     struct ndpi_flow_struct *flow, ndpi_risk_enum r) {
3279
556
  if(ndpi_isset_risk(flow, r)) {
3280
0
    u_int8_t i, j;
3281
0
    ndpi_risk v = 1ull << r;
3282
3283
0
    flow->risk &= ~v;
3284
3285
0
    if(!is_flowrisk_info_enabled(ndpi_str, r))
3286
0
      return;
3287
3288
0
    for(i = 0; i < flow->num_risk_infos; i++) {
3289
0
      if(flow->risk_infos[i].id == r) {
3290
0
        flow->risk_infos[i].id = 0;
3291
0
        if(flow->risk_infos[i].info) {
3292
0
          ndpi_free(flow->risk_infos[i].info);
3293
0
          flow->risk_infos[i].info = NULL;
3294
0
        }
3295
0
        for(j = i + 1; j < flow->num_risk_infos; j++) {
3296
0
          flow->risk_infos[j - 1].id = flow->risk_infos[j].id;
3297
0
          flow->risk_infos[j - 1].info = flow->risk_infos[j].info;
3298
0
        }
3299
0
        flow->num_risk_infos--;
3300
0
      }
3301
0
    }
3302
0
  }
3303
556
}
3304
3305
/* ******************************************************************** */
3306
3307
12.8k
int ndpi_isset_risk(struct ndpi_flow_struct *flow, ndpi_risk_enum r) {
3308
12.8k
  ndpi_risk v = 1ull << r;
3309
3310
12.8k
  return(((flow->risk & v) == v) ?  1 : 0);
3311
12.8k
}
3312
3313
/* ******************************************************************** */
3314
3315
0
int ndpi_is_printable_buffer(uint8_t const * const buf, size_t len) {
3316
0
  int retval = 1;
3317
0
  size_t i;
3318
3319
0
  for(i = 0; i < len; ++i) {
3320
0
    if(ndpi_isprint(buf[i]) == 0) {
3321
0
      retval = 0;
3322
0
    }
3323
0
  }
3324
3325
0
  return retval;
3326
0
}
3327
3328
/* ******************************************************************** */
3329
3330
0
int ndpi_normalize_printable_string(char * const str, size_t len) {
3331
0
  int retval = 1;
3332
0
  size_t i;
3333
3334
0
  for(i = 0; i < len; ++i) {
3335
0
    if(ndpi_isprint(str[i]) == 0) {
3336
0
      str[i] = '?';
3337
0
      retval = 0;
3338
0
    }
3339
0
  }
3340
3341
0
  return retval;
3342
0
}
3343
3344
/* ******************************************************************** */
3345
3346
/*
3347
  This function checks if a symbolic hostname is valid or not.
3348
3349
  Validation Rules Implemented:
3350
  - Hostname must not be NULL or empty
3351
  - Total length must be b$ 253 characters
3352
  - Each label (part between dots) must be 1-63 characters
3353
  - Can only contain alphanumeric characters and hyphens
3354
  - Each label must start and end with a letter or digit
3355
  - Must not start or end with a dot
3356
  - Must contain at least one label
3357
*/
3358
192
bool ndpi_is_valid_hostname(char * const hostname, size_t len) {
3359
192
  const char *p;
3360
192
  size_t label_len = 0, idx = 0;
3361
192
  bool has_valid_label = false;
3362
3363
192
  if(!hostname || len == 0 || *hostname == '\0')
3364
0
    return(false); /* Empty string or NULL pointer */
3365
3366
192
  if(len > 253) /* Maximum length of a full hostname */
3367
13
    return(false);
3368
3369
  /* Check each label (part between dots) */
3370
179
  p = hostname;
3371
3372
593
  while ((idx < len) && *p) {
3373
575
    if(*p == '.') {
3374
      /* Check previous label */
3375
67
      if(label_len == 0 || (label_len > 63))
3376
7
  return(false); /* Empty label or too long */
3377
3378
60
      label_len = 0;
3379
60
      idx++;
3380
60
      p++;
3381
60
      has_valid_label = true;
3382
60
      continue;
3383
67
    }
3384
3385
508
    if(!(isalnum((unsigned char)*p) || *p == '-'))
3386
154
      return(false); /* Invalid character */
3387
3388
    /* Check first and last character of label */
3389
354
    if(label_len == 0) {
3390
127
      if(!isalnum((unsigned char)*p))
3391
0
  return(false); /* Label must start with letter or digit */
3392
127
    }
3393
3394
354
    label_len++;
3395
354
    if(label_len > 63)
3396
0
      return(false); /* Label too long */
3397
3398
354
    idx++;
3399
354
    p++;
3400
354
  }
3401
3402
  /* Check last label */
3403
18
  if(label_len == 0)
3404
0
    return(false); /* Ends with a dot */
3405
3406
18
  if(!isalnum(hostname[idx-1]))
3407
3
    return(false); /* Label must end with letter or digit */
3408
3409
15
  return(has_valid_label || len > 0); /* At least one label exists */
3410
18
}
3411
3412
/* ******************************************************************** */
3413
3414
385
float ndpi_entropy(u_int8_t const * const buf, size_t len) {
3415
385
  float entropy = 0.0f;
3416
385
  u_int32_t byte_counters[256];
3417
385
  size_t i;
3418
3419
385
  memset(byte_counters, 0, sizeof(byte_counters));
3420
3421
1.16M
  for(i = 0; i < len; ++i) {
3422
1.16M
    byte_counters[buf[i]]++;
3423
1.16M
  }
3424
3425
98.9k
  for(i = 0; i < sizeof(byte_counters) / sizeof(byte_counters[0]); ++i) {
3426
98.5k
    if(byte_counters[i] == 0) {
3427
58.3k
      continue;
3428
58.3k
    }
3429
3430
40.2k
    float const p = (float)byte_counters[i] / len;
3431
40.2k
    entropy += p * log2f(1 / p);
3432
40.2k
  }
3433
3434
385
  return entropy;
3435
385
}
3436
3437
/* ******************************************************************** */
3438
3439
/* Losely implemented by: https://redirect.cs.umbc.edu/courses/graduate/CMSC691am/student%20talks/CMSC%20691%20Malware%20-%20Entropy%20Analysis%20Presentation.pdf */
3440
869
char *ndpi_entropy2str(float entropy, char *buf, size_t len) {
3441
869
  if (buf == NULL) {
3442
473
    return NULL;
3443
473
  }
3444
3445
396
  static const char entropy_fmtstr[] = "Entropy: %.3f (%s?)";
3446
396
  if (NDPI_ENTROPY_ENCRYPTED_OR_RANDOM(entropy)) {
3447
153
    snprintf(buf, len, entropy_fmtstr, entropy, "Encrypted or Random");
3448
243
  } else if (NDPI_ENTROPY_EXECUTABLE_ENCRYPTED(entropy)) {
3449
1
    snprintf(buf, len, entropy_fmtstr, entropy, "Encrypted Executable");
3450
242
  } else if (NDPI_ENTROPY_EXECUTABLE_PACKED(entropy)) {
3451
0
    snprintf(buf, len, entropy_fmtstr, entropy, "Compressed Executable");
3452
242
  } else if (NDPI_ENTROPY_EXECUTABLE(entropy)) {
3453
100
    snprintf(buf, len, entropy_fmtstr, entropy, "Executable");
3454
142
  } else {
3455
142
    snprintf(buf, len, entropy_fmtstr, entropy, "Unknown");
3456
142
  }
3457
3458
396
  return buf;
3459
869
}
3460
3461
/* ******************************************************************** */
3462
3463
void ndpi_entropy2risk(struct ndpi_detection_module_struct *ndpi_struct,
3464
613
                       struct ndpi_flow_struct *flow) {
3465
613
  char str[64];
3466
3467
613
  if (NDPI_ENTROPY_PLAINTEXT(flow->entropy))
3468
506
    goto reset_risk;
3469
3470
107
  if (flow->detected_protocol_stack[0] == NDPI_PROTOCOL_TLS ||
3471
107
      flow->detected_protocol_stack[1] == NDPI_PROTOCOL_TLS ||
3472
107
      flow->detected_protocol_stack[0] == NDPI_PROTOCOL_QUIC ||
3473
107
      flow->detected_protocol_stack[1] == NDPI_PROTOCOL_QUIC ||
3474
107
      flow->detected_protocol_stack[0] == NDPI_PROTOCOL_DTLS ||
3475
107
      flow->detected_protocol_stack[1] == NDPI_PROTOCOL_DTLS) {
3476
0
    flow->skip_entropy_check = 1;
3477
0
    goto reset_risk;
3478
0
  }
3479
3480
107
  if (flow->confidence != NDPI_CONFIDENCE_DPI &&
3481
88
      flow->confidence != NDPI_CONFIDENCE_DPI_CACHE) {
3482
88
    ndpi_set_risk(ndpi_struct, flow, NDPI_SUSPICIOUS_ENTROPY,
3483
88
                  ndpi_entropy2str(flow->entropy, str, sizeof(str)));
3484
88
    return;
3485
88
  }
3486
3487
19
  if (ndpi_isset_risk(flow, NDPI_MALWARE_HOST_CONTACTED) ||
3488
19
      ndpi_isset_risk(flow, NDPI_BINARY_DATA_TRANSFER) ||
3489
19
      ndpi_isset_risk(flow, NDPI_BINARY_APPLICATION_TRANSFER) ||
3490
19
      ndpi_isset_risk(flow, NDPI_POSSIBLE_EXPLOIT) ||
3491
19
      ndpi_isset_risk(flow, NDPI_HTTP_SUSPICIOUS_CONTENT) ||
3492
19
      ndpi_isset_risk(flow, NDPI_DNS_SUSPICIOUS_TRAFFIC) ||
3493
12
      ndpi_isset_risk(flow, NDPI_MALFORMED_PACKET) ||
3494
3
      (flow->category == NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT &&
3495
0
       (flow->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP ||
3496
0
        flow->detected_protocol_stack[1] == NDPI_PROTOCOL_HTTP)) ||
3497
3
      flow->category == NDPI_PROTOCOL_CATEGORY_DATA_TRANSFER ||
3498
3
      flow->category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED ||
3499
3
      flow->category == NDPI_PROTOCOL_CATEGORY_WEB)
3500
16
  {
3501
16
    ndpi_set_risk(ndpi_struct, flow, NDPI_SUSPICIOUS_ENTROPY,
3502
16
                  ndpi_entropy2str(flow->entropy, str, sizeof(str)));
3503
16
    return;
3504
16
  }
3505
3506
509
reset_risk:
3507
509
  ndpi_unset_risk(ndpi_struct, flow, NDPI_SUSPICIOUS_ENTROPY);
3508
509
}
3509
3510
/* ******************************************************************** */
3511
3512
759
static inline uint16_t get_n16bit(uint8_t const * cbuf) {
3513
759
  uint16_t r = ((uint16_t)cbuf[0]) | (((uint16_t)cbuf[1]) << 8);
3514
759
  return r;
3515
759
}
3516
3517
1
u_int16_t icmp4_checksum(const u_int8_t * buf, size_t len) {
3518
1
  u_int32_t checksum = 0;
3519
3520
  /*
3521
   * The first two bytes of the icmp header are required.
3522
   * The next two bytes is the checksum, which we want to ignore.
3523
   */
3524
3525
760
  for(; len > 1; len -= 2) {
3526
759
    checksum += get_n16bit(buf);
3527
759
    buf += 2;
3528
759
  }
3529
3530
1
  if(len == 1) {
3531
0
    checksum += *buf;
3532
0
  }
3533
3534
1
  checksum = (checksum >> 16) + (checksum & 0xFFFF);
3535
1
  checksum += (checksum >> 16);
3536
3537
1
  return ~checksum;
3538
1
}
3539
3540
/* ******************************************* */
3541
3542
1.03k
char* ndpi_get_flow_name(struct ndpi_flow_struct *flow) {
3543
1.03k
  if(!flow) goto no_flow_info;
3544
3545
559
  if(flow->host_server_name[0] != '\0')
3546
184
    return((char*)flow->host_server_name);
3547
3548
849
 no_flow_info:
3549
849
  return((char*)"");
3550
559
}
3551
3552
/* ******************************************* */
3553
3554
813
void load_common_alpns(struct ndpi_detection_module_struct *ndpi_str) {
3555
  /* see: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */
3556
813
  const char* const common_alpns[] = {
3557
813
    "http/0.9", "http/1.0", "http/1.1",
3558
813
    "spdy/1", "spdy/2", "spdy/3", "spdy/3.1",
3559
813
    "stun.turn", "stun.nat-discovery",
3560
813
    "h2", "h2c", "h2-16", "h2-15", "h2-14", "h2-fb",
3561
813
    "webrtc", "c-webrtc",
3562
813
    "ftp", "imap", "pop3", "managesieve", "coap",
3563
813
    "xmpp-client", "xmpp-server",
3564
813
    "acme-tls/1",
3565
813
    "mqtt", "dot", "ntske/1", "sunrpc",
3566
813
    "h3",
3567
813
    "smb",
3568
813
    "irc",
3569
3570
    /* QUIC ALPNs */
3571
813
    "h3-T051", "h3-T050",
3572
813
    "h3-34", "h3-33", "h3-32", "h3-31", "h3-30", "h3-29", "h3-28", "h3-27", "h3-24", "h3-22",
3573
813
    "hq-34", "hq-33", "hq-32", "hq-31", "hq-30", "hq-29", "hq-28", "hq-27", "hq-interop",
3574
813
    "h3-fb-05", "h1q-fb",
3575
813
    "doq-i00",
3576
3577
    /* ApplePush */
3578
813
    "apns-security-v3", "apns-pack-v1",
3579
3580
    NULL /* end */
3581
813
  };
3582
813
  u_int i;
3583
3584
47.9k
  for(i=0; common_alpns[i] != NULL; i++) {
3585
47.1k
    AC_PATTERN_t ac_pattern;
3586
3587
47.1k
    memset(&ac_pattern, 0, sizeof(ac_pattern));
3588
47.1k
    ac_pattern.astring      = ndpi_strdup((char*)common_alpns[i]);
3589
47.1k
    if(!ac_pattern.astring) {
3590
242
      NDPI_LOG_ERR(ndpi_str, "Unable to add %s [mem alloc error]\n", common_alpns[i]);
3591
242
      continue;
3592
242
    }
3593
46.9k
    ac_pattern.length       = strlen(common_alpns[i]);
3594
3595
46.9k
    if(ac_automata_add(ndpi_str->common_alpns_automa.ac_automa, &ac_pattern) != ACERR_SUCCESS) {
3596
1.49k
      ndpi_free(ac_pattern.astring);
3597
1.49k
      NDPI_LOG_ERR(ndpi_str, "Unable to add %s\n", common_alpns[i]);
3598
1.49k
    }
3599
46.9k
  }
3600
813
}
3601
3602
/* ******************************************* */
3603
3604
u_int8_t is_a_common_alpn(struct ndpi_detection_module_struct *ndpi_str,
3605
0
        const char *alpn_to_check, u_int alpn_to_check_len) {
3606
0
  ndpi_automa *automa = &ndpi_str->common_alpns_automa;
3607
3608
0
  if(automa->ac_automa) {
3609
0
    AC_TEXT_t ac_input_text;
3610
0
    AC_REP_t match;
3611
3612
0
    memset(&match, 0, sizeof(match));
3613
0
    ac_input_text.astring = (char*)alpn_to_check, ac_input_text.length = alpn_to_check_len;
3614
0
    ac_input_text.option = 0;
3615
3616
0
    if(ac_automata_search(automa->ac_automa, &ac_input_text, &match) > 0)
3617
0
      return(1);
3618
0
  }
3619
3620
0
  return(0);
3621
0
}
3622
3623
/* ******************************************* */
3624
3625
3.66M
u_int8_t ndpi_is_valid_protoId(const struct ndpi_detection_module_struct *ndpi_str, u_int16_t protoId) {
3626
3.66M
  if(!ndpi_str)
3627
343
    return 0;
3628
3.66M
  return(protoId >= ndpi_str->num_supported_protocols ? 0 : 1);
3629
3.66M
}
3630
3631
/* ******************************************* */
3632
3633
u_int8_t ndpi_is_encrypted_proto(struct ndpi_detection_module_struct *ndpi_str,
3634
0
                                 ndpi_master_app_protocol proto) {
3635
0
  if(proto.master_protocol == NDPI_PROTOCOL_UNKNOWN && ndpi_is_valid_protoId(ndpi_str, proto.app_protocol)) {
3636
0
    return(!ndpi_str->proto_defaults[proto.app_protocol].isClearTextProto);
3637
0
  } else if(ndpi_is_valid_protoId(ndpi_str, proto.master_protocol) && ndpi_is_valid_protoId(ndpi_str, proto.app_protocol)) {
3638
0
    if(ndpi_str->proto_defaults[proto.master_protocol].isClearTextProto
3639
0
       && (!ndpi_str->proto_defaults[proto.app_protocol].isClearTextProto))
3640
0
      return(0);
3641
0
    else
3642
0
      return((ndpi_str->proto_defaults[proto.master_protocol].isClearTextProto
3643
0
        && ndpi_str->proto_defaults[proto.app_protocol].isClearTextProto) ? 0 : 1);
3644
0
  } else
3645
0
    return(0);
3646
0
}
3647
3648
/* ******************************************* */
3649
3650
765
u_int32_t ndpi_get_flow_error_code(struct ndpi_flow_struct *flow) {
3651
765
  switch(flow->detected_protocol_stack[0] /* proto.app_protocol */) {
3652
0
  case NDPI_PROTOCOL_DNS:
3653
0
    return(flow->protos.dns.reply_code);
3654
3655
189
  case NDPI_PROTOCOL_HTTP:
3656
189
    return(flow->http.response_status_code);
3657
3658
0
  case NDPI_PROTOCOL_SNMP:
3659
0
    return(flow->protos.snmp.error_status);
3660
765
 }
3661
3662
576
  return(0);
3663
765
}
3664
3665
/* ******************************************* */
3666
3667
int ndpi_vsnprintf(char * str, size_t size, char const * format, va_list va_args)
3668
11.5k
{
3669
#ifdef WIN32
3670
  if((str == NULL) || (size == 0) || (format == NULL)) {
3671
    return -1;
3672
  }
3673
3674
  int ret = vsnprintf_s(str, size, _TRUNCATE, format, va_args);
3675
3676
  if(ret < 0) {
3677
    return size;
3678
  } else {
3679
    return ret;
3680
  }
3681
#else
3682
11.5k
  return vsnprintf(str, size, format, va_args);
3683
11.5k
#endif
3684
11.5k
}
3685
3686
/* ******************************************* */
3687
3688
struct tm *ndpi_gmtime_r(const time_t *timep,
3689
                         struct tm *result)
3690
0
{
3691
#if defined(WIN32)
3692
  gmtime_s(result, timep);
3693
  return result;
3694
#else
3695
0
  return gmtime_r(timep, result);
3696
0
#endif
3697
0
}
3698
3699
/* ******************************************* */
3700
3701
11.5k
int ndpi_snprintf(char * str, size_t size, char const * format, ...) {
3702
11.5k
  va_list va_args;
3703
3704
11.5k
  va_start(va_args, format);
3705
11.5k
  int ret = ndpi_vsnprintf(str, size, format, va_args);
3706
11.5k
  va_end(va_args);
3707
3708
11.5k
  return ret;
3709
11.5k
}
3710
3711
/* ******************************************* */
3712
3713
static int risk_infos_pair_cmp (const void *_a, const void *_b)
3714
3.36k
{
3715
3.36k
  struct ndpi_risk_information *a = (struct ndpi_risk_information *)_a;
3716
3.36k
  struct ndpi_risk_information *b = (struct ndpi_risk_information *)_b;
3717
3718
3.36k
  return b->id - a->id;
3719
3.36k
}
3720
3721
/* ******************************************* */
3722
3723
char* ndpi_get_flow_risk_info(struct ndpi_flow_struct *flow,
3724
            char *out, u_int out_len,
3725
765
            u_int8_t use_json) {
3726
765
  u_int i, offset = 0;
3727
765
  struct ndpi_risk_information *ordered_risk_infos;
3728
3729
765
  if((out == NULL)
3730
765
     || (flow == NULL)
3731
765
     || (flow->num_risk_infos == 0))
3732
140
    return(NULL);
3733
3734
  /* Ordered list of flow risk infos */
3735
625
  ordered_risk_infos = ndpi_malloc(sizeof(flow->risk_infos));
3736
625
  if(!ordered_risk_infos)
3737
1
    return(NULL);
3738
624
  memcpy(ordered_risk_infos, flow->risk_infos, sizeof(flow->risk_infos));
3739
624
  qsort(ordered_risk_infos, flow->num_risk_infos, sizeof(struct ndpi_risk_information), risk_infos_pair_cmp);
3740
3741
624
  if(use_json) {
3742
624
    ndpi_serializer serializer;
3743
624
    u_int32_t buffer_len;
3744
624
    char *buffer;
3745
3746
624
    if(ndpi_init_serializer(&serializer, ndpi_serialization_format_json) == -1) {
3747
0
      ndpi_free(ordered_risk_infos);
3748
0
      return(NULL);
3749
0
    }
3750
3751
3.19k
    for(i=0; i<flow->num_risk_infos; i++)
3752
2.57k
      ndpi_serialize_uint32_string(&serializer,
3753
2.57k
                                   ordered_risk_infos[i].id,
3754
2.57k
                                   ordered_risk_infos[i].info);
3755
3756
624
    buffer = ndpi_serializer_get_buffer(&serializer, &buffer_len);
3757
3758
624
    if(buffer && (buffer_len > 0)) {
3759
624
      u_int l = ndpi_min(out_len-1, buffer_len);
3760
3761
624
      strncpy(out, buffer, l);
3762
624
      out[l] = '\0';
3763
624
    }
3764
3765
624
    ndpi_term_serializer(&serializer);
3766
3767
624
    ndpi_free(ordered_risk_infos);
3768
624
    return(out);
3769
624
  } else {
3770
0
    out[0] = '\0', out_len--;
3771
3772
0
    for(i=0; (i<flow->num_risk_infos) && (out_len > offset); i++) {
3773
0
      int rc = snprintf(&out[offset], out_len-offset, "%s%s",
3774
0
      (i == 0) ? "" : " / ",
3775
0
      ordered_risk_infos[i].info);
3776
3777
0
      if(rc <= 0)
3778
0
  break;
3779
0
      else
3780
0
  offset += rc;
3781
0
    }
3782
3783
0
    if(offset > out_len) offset = out_len;
3784
3785
0
    out[offset] = '\0';
3786
3787
0
    ndpi_free(ordered_risk_infos);
3788
0
    return(out[0] == '\0' ? NULL : out);
3789
0
  }
3790
624
}
3791
3792
/* ******************************************* */
3793
/*
3794
  This function checks if a flow having the specified risk
3795
  parameters is an exception (i.e. the flow risk should not
3796
  be triggered) or not.
3797
3798
  You can use this function to check if a flow that
3799
  as a flow risk will match an exception or not.
3800
*/
3801
u_int8_t ndpi_check_flow_risk_exceptions(struct ndpi_detection_module_struct *ndpi_str,
3802
           u_int num_params,
3803
1.50k
           ndpi_risk_params params[]) {
3804
1.50k
  u_int i;
3805
3806
1.50k
  if(!ndpi_str)
3807
98
    return(0);
3808
3809
4.01k
  for(i=0; i<num_params; i++) {
3810
2.71k
    switch(params[i].id) {
3811
704
    case NDPI_PARAM_HOSTNAME:
3812
704
      if(ndpi_check_hostname_risk_exception(ndpi_str, NULL, (char*)params[i].value))
3813
0
  return(1);
3814
704
      break;
3815
3816
704
    case NDPI_PARAM_ISSUER_DN:
3817
704
      if(ndpi_check_issuerdn_risk_exception(ndpi_str, (char*)params[i].value))
3818
103
  return(1);
3819
601
      break;
3820
3821
601
    case NDPI_PARAM_HOST_IPV4:
3822
601
      if(ndpi_check_ipv4_exception(ndpi_str, NULL, *((u_int32_t*)params[i].value)))
3823
0
  return(1);
3824
601
      break;
3825
3826
704
    default:
3827
704
      NDPI_LOG_ERR(ndpi_str, "Ignored risk parameter id %u\n", params[i].id);
3828
704
      break;
3829
2.71k
    }
3830
2.71k
  }
3831
3832
1.30k
  return(0);
3833
1.40k
}
3834
3835
/* ******************************************* */
3836
3837
1
int64_t asn1_ber_decode_length(const unsigned char *payload, int payload_len, u_int16_t *value_len) {
3838
1
  unsigned int value, i;
3839
3840
1
  if(payload_len <= 0)
3841
0
    return -1;
3842
3843
  /* Malformed */
3844
1
  if(payload[0] == 0xFF)
3845
0
    return -1;
3846
3847
  /* Definite, short */
3848
1
  if(payload[0] <= 0x80) {
3849
1
    *value_len = 1;
3850
1
    return payload[0];
3851
1
  }
3852
  /* Indefinite, unsupported */
3853
0
  if((payload[0] & 0x7F) == 0)
3854
0
    return -1;
3855
3856
0
  *value_len = payload[0] & 0x7F;
3857
  /* We support only 4 additional length octets */
3858
0
  if(*value_len > 4 ||
3859
0
     payload_len <= *value_len + 1)
3860
0
    return -1;
3861
3862
0
  value = 0;
3863
0
  for (i = 1; i <= *value_len; i++) {
3864
0
    value |= (unsigned int)payload[i] << ((*value_len) - i) * 8;
3865
0
  }
3866
3867
0
  (*value_len) += 1;
3868
0
  return value;
3869
0
}
3870
3871
/* ******************************************* */
3872
3873
18
char* ndpi_intoav4(unsigned int addr, char* buf, u_int16_t bufLen) {
3874
18
  char *cp;
3875
18
  int n;
3876
3877
18
  cp = &buf[bufLen];
3878
18
  *--cp = '\0';
3879
3880
18
  n = 4;
3881
72
  do {
3882
72
    u_int byte = addr & 0xff;
3883
3884
72
    *--cp = byte % 10 + '0';
3885
72
    byte /= 10;
3886
72
    if(byte > 0) {
3887
63
      *--cp = byte % 10 + '0';
3888
63
      byte /= 10;
3889
63
      if(byte > 0)
3890
44
  *--cp = byte + '0';
3891
63
    }
3892
72
    if(n > 1)
3893
54
      *--cp = '.';
3894
72
    addr >>= 8;
3895
72
  } while (--n > 0);
3896
3897
18
  return(cp);
3898
18
}
3899
3900
/* ****************************************************** */
3901
3902
0
char* ndpi_intoav6(struct ndpi_in6_addr *addr, char* buf, u_int16_t bufLen) {
3903
0
  char *ret;
3904
0
  const u_int8_t use_brackets = 0;
3905
3906
0
  if(use_brackets == 0) {
3907
0
    ret = (char*)inet_ntop(AF_INET6, (struct in6_addr *)addr, buf, bufLen);
3908
3909
0
    if(ret == NULL) {
3910
      /* Internal error (buffer too short */
3911
0
      buf[0] = '\0';
3912
0
    }
3913
0
  } else {
3914
0
    ret = (char*)inet_ntop(AF_INET6, (struct in6_addr *)addr, &buf[1], bufLen-1);
3915
3916
0
    if(ret == NULL) {
3917
      /* Internal error (buffer too short) */
3918
0
      buf[0] = '\0';
3919
0
    } else {
3920
0
      int len = strlen(ret);
3921
3922
0
      buf[0] = '[';
3923
0
      buf[len+1] = ']';
3924
0
      buf[len+2] = '\0';
3925
0
    }
3926
0
  }
3927
3928
0
  return(buf);
3929
0
}
3930
3931
/* ******************************************* */
3932
3933
/* Find the nearest (>=) value of x */
3934
860
u_int32_t ndpi_nearest_power_of_two(u_int32_t x) {
3935
860
  x--;
3936
3937
860
  x |= x >> 1;
3938
860
  x |= x >> 2;
3939
860
  x |= x >> 4;
3940
860
  x |= x >> 8;
3941
860
  x |= x >> 16;
3942
3943
860
  x++;
3944
860
  return(x);
3945
860
}
3946
3947
/* ******************************************* */
3948
3949
982
int tpkt_verify_hdr(const struct ndpi_packet_struct * const packet) {
3950
982
  return ((packet->tcp != NULL) && (packet->payload_packet_len > 4) &&
3951
958
          (packet->payload[0] == 3) && (packet->payload[1] == 0) &&
3952
0
          (get_u_int16_t(packet->payload,2) == htons(packet->payload_packet_len)));
3953
982
}
3954
3955
/* ******************************************* */
3956
3957
int64_t ndpi_strtonum(const char *numstr, int64_t minval,
3958
44.3k
          int64_t maxval, const char **errstrp, int base) {
3959
44.3k
  int64_t val = 0;
3960
44.3k
  char* endptr;
3961
3962
44.3k
  if (minval > maxval) {
3963
0
    *errstrp = "minval > maxval";
3964
0
    return 0;
3965
0
  }
3966
3967
44.3k
  errno = 0;    /* To distinguish success/failure after call */
3968
44.3k
  val = (int64_t)strtoll(numstr, &endptr, base);
3969
3970
44.3k
  if((val == LLONG_MIN && errno == ERANGE) || (val < minval)) {
3971
82
    *errstrp = "value too small";
3972
82
    return 0;
3973
82
  }
3974
3975
44.2k
  if((val == LLONG_MAX && errno == ERANGE) || (val > maxval )) {
3976
0
    *errstrp = "value too large";
3977
0
    return 0;
3978
0
  }
3979
3980
44.2k
  if(errno != 0 && val == 0) {
3981
0
    *errstrp = "generic error";
3982
0
    return 0;
3983
0
  }
3984
3985
44.2k
  if(endptr == numstr) {
3986
124
    *errstrp = "No digits were found";
3987
124
    return 0;
3988
124
  }
3989
  /* Like the original strtonum, we allow further characters after the number */
3990
3991
44.1k
  *errstrp = NULL;
3992
44.1k
  return val;
3993
44.2k
}
3994
3995
/* ****************************************************** */
3996
3997
206
char* ndpi_strrstr(const char *haystack, const char *needle) {
3998
206
  if (!haystack || !needle) {
3999
0
    return NULL;
4000
0
  }
4001
4002
206
  if (*needle == '\0') {
4003
0
    return (char*) haystack + strlen(haystack);
4004
0
  }
4005
4006
206
  const char *last_occurrence = NULL;
4007
4008
524
  while (true) {
4009
524
    const char *current_pos = strstr(haystack, needle);
4010
4011
524
    if (!current_pos) {
4012
206
      break;
4013
206
    }
4014
4015
318
    last_occurrence = current_pos;
4016
318
    haystack = current_pos + 1;
4017
318
  }
4018
4019
206
  return (char*) last_occurrence;
4020
206
}
4021
4022
/* ************************************************************** */
4023
4024
192
void *ndpi_memrchr(const void *m, int c, size_t n) {
4025
192
  const unsigned char *s = m;
4026
4027
192
  c = (unsigned char)c;
4028
21.1k
  while(n--)
4029
21.0k
    if(s[n]==c)
4030
70
      return (void *)(s+n);
4031
4032
122
  return 0;
4033
192
}
4034
4035
4036
/* ************************************************************** */
4037
4038
2.64k
int ndpi_str_endswith(const char *s, const char *suffix) {
4039
2.64k
  size_t slen = strlen(s);
4040
2.64k
  size_t suffixlen = strlen(suffix);
4041
4042
2.64k
  return((slen >= suffixlen) && (!memcmp(&s[slen - suffixlen], suffix, suffixlen)));
4043
2.64k
}
4044
4045
/* ******************************************* */
4046
4047
const char *ndpi_lru_cache_idx_to_name(lru_cache_type idx)
4048
6.65k
{
4049
6.65k
  const char *names[NDPI_LRUCACHE_MAX] = { "ookla", "bittorrent", "stun",
4050
6.65k
                                           "tls_cert", "mining", "msteams",
4051
6.65k
                                           "fpc_dns", "signal" };
4052
4053
6.65k
  if(idx < 0 || idx >= NDPI_LRUCACHE_MAX)
4054
720
    return "unknown";
4055
5.93k
  return names[idx];
4056
6.65k
}
4057
4058
/* ******************************************* */
4059
4060
160k
size_t ndpi_compress_str(const char * in, size_t len, char * out, size_t bufsize) {
4061
160k
  size_t ret = shoco_compress(in, len, out, bufsize);
4062
4063
160k
  if(ret > bufsize)
4064
15
    return(0); /* Better not to compress data (it is longer than the uncompressed data) */
4065
4066
160k
  return(ret);
4067
160k
}
4068
4069
/* ******************************************* */
4070
4071
0
size_t ndpi_decompress_str(const char * in, size_t len, char * out, size_t bufsize) {
4072
0
  return(shoco_decompress(in, len, out, bufsize));
4073
0
}
4074
4075
/* ******************************************* */
4076
4077
static u_char ndpi_domain_mapper[256];
4078
static bool ndpi_domain_mapper_initialized = false;
4079
4080
407k
#define IGNORE_CHAR           0xFF
4081
440k
#define NUM_BITS_NIBBLE       6 /* each 'nibble' is encoded with 6 bits */
4082
406k
#define NIBBLE_ELEM_OFFSET    24
4083
4084
/* Used fo encoding domain names 8 bits -> 6 bits */
4085
1
static void ndpi_domain_mapper_init() {
4086
1
  u_int i;
4087
1
  u_char idx = 1 /* start from 1 to make sure 0 is no ambiguous */;
4088
4089
1
  memset(ndpi_domain_mapper, IGNORE_CHAR, 256);
4090
4091
27
  for(i='a'; i<= 'z'; i++)
4092
26
    ndpi_domain_mapper[i] = idx++;
4093
4094
11
  for(i='0'; i<= '9'; i++)
4095
10
    ndpi_domain_mapper[i] = idx++;
4096
4097
1
  ndpi_domain_mapper['-'] = idx++;
4098
1
  ndpi_domain_mapper['_'] = idx++;
4099
1
  ndpi_domain_mapper['.'] = idx++;
4100
1
}
4101
4102
/* ************************************************ */
4103
4104
u_int ndpi_encode_domain(struct ndpi_detection_module_struct *ndpi_str,
4105
160k
       char *domain, char *out, u_int out_len) {
4106
160k
  u_int out_idx = 0, i, buf_shift = 0, domain_buf_len, compressed_len, suffix_len, domain_len;
4107
160k
  u_int32_t value = 0;
4108
160k
  u_char domain_buf[256], compressed[128];
4109
160k
  u_int64_t domain_id = 0;
4110
160k
  const char *suffix;
4111
4112
160k
  if(!ndpi_domain_mapper_initialized) {
4113
1
    ndpi_domain_mapper_init();
4114
1
    ndpi_domain_mapper_initialized = true;
4115
1
  }
4116
4117
160k
  domain_len = strlen(domain);
4118
4119
160k
  if(domain_len >= (out_len-3))
4120
0
    return(0);
4121
4122
160k
  if(domain_len <= 4)
4123
77
    return((u_int)snprintf(out, out_len, "%s", domain));  /* Too short */
4124
4125
  /* [1] Encode the domain in 6 bits */
4126
160k
  suffix = ndpi_get_host_domain_suffix(ndpi_str, domain, &domain_id);
4127
4128
160k
  if(suffix == NULL)
4129
0
    return((u_int)snprintf(out, out_len, "%s", domain));  /* Unknown suffix */
4130
4131
160k
  snprintf((char*)domain_buf, sizeof(domain_buf), "%s", domain);
4132
160k
  domain_buf_len = strlen((char*)domain_buf), suffix_len = strlen(suffix);
4133
4134
160k
  if(domain_buf_len > suffix_len) {
4135
44.9k
    snprintf((char*)domain_buf, sizeof(domain_buf), "%s", domain);
4136
44.9k
    domain_buf_len = domain_buf_len-suffix_len-1;
4137
44.9k
    domain_buf[domain_buf_len] = '\0';
4138
4139
452k
    for(i=0; domain_buf[i] != '\0'; i++) {
4140
407k
      u_int32_t mapped_idx = ndpi_domain_mapper[domain_buf[i]];
4141
4142
407k
      if(mapped_idx != IGNORE_CHAR) {
4143
406k
  mapped_idx <<= buf_shift;
4144
406k
  value |= mapped_idx, buf_shift += NUM_BITS_NIBBLE;
4145
4146
406k
  if(buf_shift == NIBBLE_ELEM_OFFSET) {
4147
84.0k
    memcpy(&out[out_idx], &value, 3);
4148
84.0k
    out_idx += 3;
4149
84.0k
    buf_shift = 0; /* Move to the next buffer */
4150
84.0k
    value = 0;
4151
84.0k
  }
4152
406k
      }
4153
407k
    }
4154
4155
44.9k
    if(buf_shift != 0) {
4156
34.1k
      u_int bytes = buf_shift / NUM_BITS_NIBBLE;
4157
4158
34.1k
      memcpy(&out[out_idx], &value, bytes);
4159
34.1k
      out_idx += bytes;
4160
34.1k
    }
4161
44.9k
  }
4162
4163
  /* [2] Check if compressing the string is more efficient */
4164
160k
  compressed_len = ndpi_compress_str((char*)domain_buf, domain_buf_len,
4165
160k
             (char*)compressed, sizeof(compressed));
4166
4167
160k
  if((compressed_len > 0) && ((out_idx == 0) || (compressed_len < out_idx))) {
4168
135k
    if(compressed_len >= domain_len) {
4169
      /* Compression creates a longer buffer */
4170
2.65k
      return((u_int)snprintf(out, out_len, "%s", domain));
4171
132k
    } else {
4172
132k
      compressed_len = ndpi_min(ndpi_min(compressed_len, sizeof(compressed)), out_len-3);
4173
132k
      memcpy(out, compressed, compressed_len);
4174
132k
      out_idx = compressed_len;
4175
132k
    }
4176
135k
  }
4177
4178
  /* Add trailer domainId value */
4179
158k
  out[out_idx++] = (domain_id >> 8) & 0xFF;
4180
158k
  out[out_idx++] = domain_id & 0xFF;
4181
4182
#ifdef DEBUG
4183
  {
4184
    u_int i;
4185
4186
    fprintf(stdout, "%s [len: %u][", domain, out_idx);
4187
    for(i=0; i<out_idx; i++) fprintf(stdout, "%02X", out[i] & 0xFF);
4188
    fprintf(stdout, "]\n");
4189
  }
4190
#endif
4191
4192
158k
  return(out_idx);
4193
160k
}
4194
4195
/* ****************************************************** */
4196
4197
0
static u_int8_t is_ndpi_proto(struct ndpi_flow_struct *flow, u_int16_t id) {
4198
0
  if((flow->detected_protocol_stack[0] == id)
4199
0
     || (flow->detected_protocol_stack[1] == id))
4200
0
    return(1);
4201
0
  else
4202
0
    return(0);
4203
0
}
4204
4205
/* ****************************************************** */
4206
4207
bool ndpi_serialize_flow_fingerprint(struct ndpi_detection_module_struct *ndpi_str,
4208
0
             struct ndpi_flow_struct *flow, ndpi_serializer *serializer) {
4209
0
  if(is_ndpi_proto(flow, NDPI_PROTOCOL_TLS) || is_ndpi_proto(flow, NDPI_PROTOCOL_QUIC)) {
4210
0
    if((flow->protos.tls_quic.ja4_client_raw != NULL)
4211
0
       || (flow->protos.tls_quic.ja4_client[0] != '\0')) {
4212
4213
0
      if(flow->protos.tls_quic.ja4_client_raw != NULL)
4214
0
  ndpi_serialize_string_string(serializer, "JA4r", flow->protos.tls_quic.ja4_client_raw);
4215
4216
0
      ndpi_serialize_string_string(serializer, "JA4", flow->protos.tls_quic.ja4_client);
4217
4218
0
      if(flow->host_server_name[0] != '\0') {
4219
0
  ndpi_serialize_string_string(serializer, "sni", flow->host_server_name);
4220
4221
0
  ndpi_serialize_string_string(serializer, "sni_domain",
4222
0
             ndpi_get_host_domain(ndpi_str,
4223
0
                flow->host_server_name));
4224
0
      }
4225
4226
0
      return(true);
4227
0
    }
4228
0
  } else if(is_ndpi_proto(flow, NDPI_PROTOCOL_DHCP)
4229
0
      && (flow->protos.dhcp.fingerprint[0] != '\0')) {
4230
0
    ndpi_serialize_string_string(serializer, "options", flow->protos.dhcp.options);
4231
0
    ndpi_serialize_string_string(serializer, "fingerprint", flow->protos.dhcp.fingerprint);
4232
4233
0
    if(flow->protos.dhcp.class_ident[0] != '\0')
4234
0
      ndpi_serialize_string_string(serializer, "class_identifier", flow->protos.dhcp.class_ident);
4235
4236
0
    return(true);
4237
0
  } else if(is_ndpi_proto(flow, NDPI_PROTOCOL_SSH)
4238
0
      && (flow->protos.ssh.hassh_client[0] != '\0')) {
4239
4240
0
    ndpi_serialize_string_string(serializer, "hassh_client", flow->protos.ssh.hassh_client);
4241
0
    ndpi_serialize_string_string(serializer, "client_signature", flow->protos.ssh.client_signature);
4242
0
    ndpi_serialize_string_string(serializer, "hassh_server", flow->protos.ssh.hassh_server);
4243
0
    ndpi_serialize_string_string(serializer, "server_signature", flow->protos.ssh.server_signature);
4244
4245
0
    return(true);
4246
0
  }
4247
4248
0
  return(false);
4249
0
}
4250
4251
/* ****************************************************** */
4252
4253
0
u_int ndpi_hex2bin(u_char *out, u_int out_len, u_char* in, u_int in_len) {
4254
0
  u_int i, j;
4255
4256
0
  if(((in_len+1) / 2) > out_len)
4257
0
    return(0);
4258
4259
0
  for(i=0, j=0; i<in_len; i += 2, j++) {
4260
0
    char buf[3];
4261
4262
0
    buf[0] = in[i], buf[1] = in[i+1], buf[2] = '\0';
4263
0
    out[j] = strtol(buf, NULL, 16);
4264
0
  }
4265
4266
0
  return(j);
4267
0
}
4268
4269
/* ****************************************************** */
4270
4271
0
u_int ndpi_bin2hex(u_char *out, u_int out_len, u_char* in, u_int in_len) {
4272
0
  u_int i, j;
4273
4274
0
  if (out_len < (in_len*2)) {
4275
0
    out[0] = '\0';
4276
0
    return(0);
4277
0
  }
4278
4279
0
  for(i=0, j=0; i<in_len; i++) {
4280
0
    snprintf((char*)&out[j], out_len-j, "%02X", in[i]);
4281
0
    j += 2;
4282
0
  }
4283
4284
0
  return(j);
4285
0
}
4286
4287
/* ****************************************************** */
4288
/* ****************************************************** */
4289
4290
#include "third_party/include/aes.h"
4291
4292
/*
4293
  IMPORTANT: the returned string (if not NULL) must be freed
4294
*/
4295
char* ndpi_quick_encrypt(const char *cleartext_msg,
4296
       u_int16_t cleartext_msg_len,
4297
       u_int16_t *encrypted_msg_len,
4298
0
       u_char encrypt_key[64]) {
4299
0
  char *encoded = NULL, *encoded_buf;
4300
0
  struct AES_ctx ctx;
4301
0
  int encoded_len, i, n_padding;
4302
0
  u_char nonce[24] = { 0x0 };
4303
0
  u_char binary_encrypt_key[32];
4304
4305
  /* AES, as a block cipher, does not change the size. The input size is always the output size.
4306
   * But AES, being a block cipher, requires the input to be multiple of block size (16 bytes). */
4307
0
  encoded_len = cleartext_msg_len + 16 - (cleartext_msg_len % 16);
4308
4309
0
  *encrypted_msg_len = 0;
4310
0
  encoded_buf = (char *)ndpi_calloc(encoded_len, 1);
4311
4312
0
  if (encoded_buf == NULL) {
4313
    /* Allocation failure */
4314
0
    return(NULL);
4315
0
  }
4316
4317
0
  ndpi_hex2bin(binary_encrypt_key, sizeof(binary_encrypt_key), (u_char*)encrypt_key, 64);
4318
4319
0
  memcpy(encoded_buf, cleartext_msg, cleartext_msg_len);
4320
4321
  /* PKCS5 Padding (https://www.cryptosys.net/pki/manpki/pki_paddingschemes.html) */
4322
0
  n_padding = encoded_len - cleartext_msg_len;
4323
4324
0
  for(i = encoded_len - n_padding; i < encoded_len; i++)
4325
0
    encoded_buf[i] = n_padding;
4326
4327
0
  AES_init_ctx_iv(&ctx, binary_encrypt_key, nonce);
4328
0
  AES_CBC_encrypt_buffer(&ctx, (uint8_t*)encoded_buf, encoded_len);
4329
4330
0
  encoded = ndpi_base64_encode((const unsigned char *)encoded_buf, encoded_len);
4331
0
  ndpi_free(encoded_buf);
4332
4333
0
  if(encoded)
4334
0
    *encrypted_msg_len = strlen(encoded);
4335
4336
0
  return(encoded);
4337
0
}
4338
4339
/* ************************************************************** */
4340
4341
char* ndpi_quick_decrypt(const char *encrypted_msg,
4342
       u_int16_t encrypted_msg_len,
4343
       u_int16_t *decrypted_msg_len,
4344
0
       u_char decrypt_key[64]) {
4345
0
  u_char nonce[24] = { 0x0 };
4346
0
  u_char binary_decrypt_key[32];
4347
0
  u_char *content;
4348
0
  size_t content_len, allocated_decoded_string = encrypted_msg_len + 8 /* padding */;
4349
0
  char *decoded_string = (char*)ndpi_calloc(sizeof(u_char), allocated_decoded_string);
4350
0
  u_int n_padding;
4351
0
  struct AES_ctx ctx;
4352
4353
0
  *decrypted_msg_len = 0;
4354
4355
0
  if(decoded_string == NULL) {
4356
    /* Allocation failure */
4357
0
    return(NULL);
4358
0
  }
4359
4360
0
  ndpi_hex2bin(binary_decrypt_key, sizeof(binary_decrypt_key), (u_char*)decrypt_key, 64);
4361
4362
0
  content = ndpi_base64_decode((const u_char*)encrypted_msg, encrypted_msg_len, &content_len);
4363
4364
0
  if((content == NULL) || (content_len == 0)) {
4365
    /* Base64 decoding error */
4366
0
    ndpi_free(decoded_string);
4367
0
    ndpi_free(content);
4368
0
    return(NULL);
4369
0
  }
4370
4371
0
  if(allocated_decoded_string < (content_len+1)) {
4372
    /* Buffer size failure */
4373
0
    ndpi_free(decoded_string);
4374
0
    ndpi_free(content);
4375
0
    return(NULL);
4376
0
  }
4377
4378
  /* AES - https://github.com/kokke/tiny-AES-c */
4379
0
  AES_init_ctx_iv(&ctx, binary_decrypt_key, nonce);
4380
0
  memcpy(decoded_string, content, content_len);
4381
0
  AES_CBC_decrypt_buffer(&ctx, (uint8_t*)decoded_string, content_len);
4382
4383
  /* Remove PKCS5 padding */
4384
0
  n_padding = decoded_string[content_len-1];
4385
4386
0
  if(content_len > n_padding) {
4387
0
    content_len = content_len - n_padding;
4388
0
    decoded_string[content_len] = 0;
4389
0
  }
4390
4391
0
  *decrypted_msg_len = content_len;
4392
4393
0
  ndpi_free(content);
4394
4395
0
  return(decoded_string);
4396
0
}
4397
4398
/* ************************************************************** */
4399
4400
765
void ndpi_fill_randombytes(unsigned char *buf, unsigned int buf_len) {
4401
765
  unsigned int i;
4402
4403
13.0k
  for(i=0; i<buf_len; i++)
4404
12.2k
    buf[i] = (unsigned char)rand();
4405
765
}
4406
4407
/* ************************************************************** */
4408
4409
0
const char* ndpi_print_os_hint(ndpi_os os_hint) {
4410
0
  switch(os_hint) {
4411
0
  case ndpi_os_windows:          return("Windows");
4412
0
  case ndpi_os_macos:            return("macOS");
4413
0
  case ndpi_os_ios_ipad_os:      return("iOS/iPad");
4414
0
  case ndpi_os_android:          return("Android");
4415
0
  case ndpi_os_linux:            return("Linux");
4416
0
  case ndpi_os_freebsd:          return("FreeBSD");
4417
0
  default:
4418
0
    break;
4419
0
  }
4420
4421
0
  return("Unknown");
4422
0
}
4423
4424
/* ************************************************************** */
4425
4426
206
char* ndpi_strndup(const char *s, size_t size) {
4427
206
  char *ret = (char*)ndpi_malloc(size+1);
4428
4429
206
  if(ret == NULL) return(NULL);
4430
4431
205
  memcpy(ret, s, size);
4432
205
  ret[size] = '\0';
4433
4434
205
  return(ret);
4435
206
}
4436
4437
/* ************************************************************** */
4438
4439
0
char *ndpi_strip_leading_trailing_spaces(char *ptr, int *ptr_len) {
4440
4441
  /* Stripping leading spaces */
4442
0
  while(*ptr_len > 0 && ptr[0] == ' ') {
4443
0
    (*ptr_len)--;
4444
0
    ptr++;
4445
0
  }
4446
0
  if(*ptr_len == 0)
4447
0
    return NULL;
4448
4449
  /* Stripping trailing spaces */
4450
0
  while(*ptr_len > 0 && ptr[*ptr_len - 1] == ' ') {
4451
0
    (*ptr_len)--;
4452
0
  }
4453
0
  if(*ptr_len == 0)
4454
0
    return NULL;
4455
4456
0
  return ptr;
4457
0
}
4458
4459
/* ************************************************************** */
4460
4461
ndpi_protocol_qoe_category_t ndpi_find_protocol_qoe(struct ndpi_detection_module_struct *ndpi_str,
4462
765
                u_int16_t protoId) {
4463
765
  if(!ndpi_is_valid_protoId(ndpi_str, protoId))
4464
50
    return(NDPI_PROTOCOL_QOE_CATEGORY_UNSPECIFIED);
4465
715
  else
4466
715
    return(ndpi_str->proto_defaults[protoId].qoeCategory);
4467
765
}
4468
4469
/* ************************************************************** */
4470
4471
/* https://gitlab.com/wireshark/wireshark/-/blob/master/epan/dissectors/packet-rtp.c */
4472
1.53k
const char* ndpi_rtp_payload_type2str(u_int8_t payload_type, u_int32_t evs_payload_type) {
4473
1.53k
  switch(payload_type) {
4474
215
  case 0:   return("ITU-T G.711 PCMU");
4475
4
  case 1:   return("USA Federal Standard FS-1016");
4476
11
  case 2:   return("ITU-T G.721");
4477
1
  case 3:   return("GSM 06.10");
4478
2
  case 4:   return("ITU-T G.723");
4479
1
  case 5:   return("DVI4 8000 samples/s");
4480
8
  case 6:   return("DVI4 16000 samples/s");
4481
5
  case 8:   return("ITU-T G.711 PCMA");
4482
0
  case 9:   return("ITU-T G.722");
4483
20
  case 10:  return("16-bit uncompressed audio, stereo");
4484
6
  case 11:  return("16-bit uncompressed audio, monaural");
4485
6
  case 12:  return("Qualcomm Code Excited Linear Predictive coding");
4486
9
  case 13:  return("Comfort noise");
4487
0
  case 14:  return("MPEG-I/II Audio");
4488
2
  case 15:  return("ITU-T G.728");
4489
2
  case 16:  return("DVI4 11025 samples/s");
4490
1
  case 17:  return("DVI4 22050 samples/s");
4491
2
  case 18:  return("ITU-T G.729");
4492
0
  case 19:  return("Comfort noise (old)");
4493
0
  case 25:  return("Sun CellB video encoding");
4494
0
  case 26:  return("JPEG-compressed video");
4495
1
  case 28:  return("'nv' program");
4496
0
  case 31:  return("ITU-T H.261");
4497
5
  case 32:  return("MPEG-I/II Video");
4498
0
  case 33:  return("MPEG-II transport streams");
4499
7
  case 34:  return("ITU-T H.263");
4500
2
  case 98:  return("AMR-WB");
4501
2
  case 118: return("AMR"); /* Adptive Multirate */
4502
0
  case 126: /* Enhanced Voice Services */
4503
766
  case 127: /* Enhanced Voice Services */
4504
766
    {
4505
766
      switch(evs_payload_type) {
4506
  /* https://gitlab.com/wireshark/wireshark/-/blob/master/epan/dissectors/packet-evs.c */
4507
4508
133
      case 0x0: return("AMR-WB IO 6.6 kbps");
4509
2
      case 0x1: return("AMR-WB IO 8.85 kbps");
4510
1
      case 0x2: return("AMR-WB IO 12.65 kbps");
4511
0
      case 0x3: return("AMR-WB IO 14.24 kbps");
4512
0
      case 0x4: return("AMR-WB IO 15.85 kbps");
4513
0
      case 0x5: return("AMR-WB IO 18.25 kbps");
4514
2
      case 0x6: return("AMR-WB IO 19.85 kbps");
4515
0
      case 0x7: return("AMR-WB IO 23.05 kbps");
4516
0
      case 0x8: return("AMR-WB IO 23.85 kbps");
4517
1
      case 0x9: return("AMR-WB IO 2.0 kbps SID");
4518
4519
  /* ** */
4520
  /* Dummy SWB 30 offset */
4521
0
      case 0x3+30: return("SWB 9.6 kbps");
4522
10
      case 0x4+30: return("SWB 13.2 kbps");
4523
0
      case 0x5+30: return("SWB 16.4 kbps");
4524
0
      case 0x6+30: return("SWB 24.4 kbps");
4525
1
      case 0x7+30: return("SWB 32 kbps");
4526
0
      case 0x8+30: return("SWB 48 kbps");
4527
0
      case 0x9+30: return("SWB 64 kbps");
4528
0
      case 0xa+30: return("SWB 96 kbps");
4529
0
      case 0xb+30: return("SWB 128 kbps");
4530
4531
4532
0
      case    48: return("EVS Primary SID 2.4");
4533
0
      case   136: return("EVS AMR-WB IO 6.6");
4534
0
      case   144: return("EVS Primary 7.2");
4535
0
      case   160: return("EVS Primary 8.0");
4536
0
      case   184: return("EVS AMR-WB IO 8.85");
4537
0
      case   192: return("EVS Primary 9.6");
4538
0
      case   256: return("EVS AMR-WB IO 12.65");
4539
0
      case   264: return("EVS Primary 13.2");
4540
0
      case   288: return("EVS AMR-WB IO 14.25");
4541
0
      case   320: return("EVS AMR-WB IO 15.85");
4542
0
      case   328: return("EVS Primary 16.4");
4543
0
      case   368: return("EVS AMR-WB IO 18.25");
4544
0
      case   400: return("EVS AMR-WB IO 19.85");
4545
0
      case   464: return("EVS AMR-WB IO 23.05");
4546
1
      case   480: return("EVS AMR-WB IO 23.85");
4547
0
      case   488: return("EVS Primary 24.4");
4548
0
      case   640: return("EVS Primary 32.0");
4549
0
      case   960: return("EVS Primary 48.0");
4550
0
      case  1280: return("EVS Primary 64.0");
4551
0
      case  1920: return("EVS Primary 96.0");
4552
0
      case  2560: return("EVS Primary 128.0");
4553
615
      default:    return("EVS 13.2");
4554
766
      }
4555
766
    }
4556
0
    break;
4557
452
  default:  return("Unknown");
4558
1.53k
  }
4559
1.53k
}
4560
4561
/* ************************************************************** */
4562
4563
0
u_char* ndpi_str_to_utf8(u_char *in, u_int in_len, u_char *out, u_int out_len) {
4564
0
  if(out_len < ((in_len*2)+1)) {
4565
0
    out[0] = '\0';
4566
0
  } else {
4567
0
    u_int i = 0, j = 0;
4568
4569
0
    while((i < in_len) && (in[i] != '\0')) {
4570
0
      if(in[i] < 0x80) {
4571
0
  out[j] = in[i];
4572
0
  i++, j++;
4573
0
      } else {
4574
0
  out[j] = 0xC0 +(in[i] >> 6);
4575
0
  j++;
4576
0
  out[j] = 0x80 | (in[i] & 0x3F);
4577
0
  i++, j++;
4578
0
      }
4579
0
    }
4580
4581
0
    out[j] = '\0';
4582
0
  }
4583
4584
0
  return(out);
4585
0
}
4586
4587
/* ************************************************************** */
4588
4589
/*
4590
    The function below checks whether the specified protocol is a
4591
      "real" master protocol or not, meaning that the protocol cannot
4592
        be encapsulated on another nDPI protocol.
4593
*/
4594
bool ndpi_is_master_only_protocol(struct ndpi_detection_module_struct *ndpi_str,
4595
1.16k
          u_int16_t proto_id) {
4596
1.16k
  if(!ndpi_is_valid_protoId(ndpi_str, proto_id))
4597
49
    return(false);
4598
1.11k
  else
4599
1.11k
    return(ndpi_str->proto_defaults[proto_id].isAppProtocol ? false : true);
4600
1.16k
}
4601
4602
/* ************************************************************** */
4603
4604
bool ndpi_normalize_protocol(struct ndpi_detection_module_struct *ndpi_str,
4605
765
           ndpi_master_app_protocol *proto) {
4606
  /* Move app to master when not an application protocol */
4607
765
  if((proto->master_protocol == NDPI_PROTOCOL_UNKNOWN)
4608
724
     && (proto->app_protocol != NDPI_PROTOCOL_UNKNOWN)) {
4609
403
    if(ndpi_is_master_only_protocol(ndpi_str, proto->app_protocol)) {
4610
395
      proto->master_protocol = proto->app_protocol;
4611
395
      proto->app_protocol = NDPI_PROTOCOL_UNKNOWN;
4612
395
      return(true);
4613
395
    } else {
4614
      #ifdef DEBUG
4615
      NDPI_LOG_ERR(ndpi_str, "INTERNAL ERROR: unexpected protocol combination %u.%u/%s",
4616
       proto->master_protocol, proto->app_protocol,
4617
       ndpi_get_proto_name(ndpi_str, proto));
4618
      #endif
4619
8
    }
4620
403
  }
4621
4622
  /* Remove duplicate protocols */
4623
370
  if((proto->master_protocol != NDPI_PROTOCOL_UNKNOWN)
4624
41
     && (proto->master_protocol == proto->app_protocol)) {
4625
0
    if(ndpi_is_master_only_protocol(ndpi_str, proto->app_protocol)) {
4626
0
      proto->master_protocol = proto->app_protocol;
4627
0
      proto->app_protocol = NDPI_PROTOCOL_UNKNOWN;
4628
0
      return(true);
4629
0
    } else {
4630
0
      proto->master_protocol = NDPI_PROTOCOL_UNKNOWN;
4631
0
      return(true);
4632
0
    }
4633
0
  }
4634
4635
370
  return(false);
4636
370
}
4637
4638
4639
4640
int ndpi_bitmask_alloc(struct ndpi_bitmask *b, u_int16_t max_bits)
4641
5.10k
{
4642
5.10k
  if(!b)
4643
0
    return -1;
4644
5.10k
  b->fds = ndpi_calloc(howmanybits(max_bits, sizeof(ndpi_ndpi_mask)), sizeof(ndpi_ndpi_mask));
4645
5.10k
  if(!b->fds)
4646
16
    return -1;
4647
5.09k
  b->max_bits = max_bits;
4648
5.09k
  b->num_fds = howmanybits(max_bits, sizeof(ndpi_ndpi_mask));
4649
5.09k
  return 0;
4650
5.10k
}
4651
4652
void ndpi_bitmask_free(struct ndpi_bitmask *b)
4653
5.35k
{
4654
5.35k
  if(b) {
4655
5.35k
    ndpi_free(b->fds);
4656
5.35k
    b->num_fds = 0;
4657
5.35k
  }
4658
5.35k
}
4659
4660
void ndpi_bitmask_set(struct ndpi_bitmask *b, u_int16_t bit)
4661
207
{
4662
207
  if(b && b->fds && bit < b->max_bits)
4663
207
    b->fds[bit / 32] |= (1ul << (bit % 32));
4664
207
}
4665
4666
void ndpi_bitmask_clear(struct ndpi_bitmask *b, u_int16_t bit)
4667
397
{
4668
397
  if(b && b->fds && bit < b->max_bits)
4669
397
    b->fds[bit / 32] &= ~(1ul << (bit % 32));
4670
397
}
4671
4672
int ndpi_bitmask_is_set(const struct ndpi_bitmask *b, u_int16_t bit)
4673
2.01M
{
4674
2.01M
  if(b && b->fds && bit < b->max_bits)
4675
2.01M
    return b->fds[bit / 32] & (1ul << (bit % 32));
4676
0
  return -1;
4677
2.01M
}
4678
4679
void ndpi_bitmask_set_all(struct ndpi_bitmask *b)
4680
3.44k
{
4681
3.44k
  if(b && b->fds)
4682
3.44k
    memset(b->fds, 0xFF, b->num_fds * sizeof(ndpi_ndpi_mask));
4683
3.44k
}
4684
4685
void ndpi_bitmask_reset(struct ndpi_bitmask *b)
4686
1.79k
{
4687
1.79k
  if(b && b->fds)
4688
1.79k
    memset(b->fds, 0x00, b->num_fds * sizeof(ndpi_ndpi_mask));
4689
1.79k
}
4690
4691
/* **************************************** */
4692
4693
33
bool ndpi_check_is_numeric_ip(char *host) {
4694
33
  unsigned char buf[sizeof(struct in6_addr)];
4695
4696
33
  if(inet_pton(AF_INET, host, buf) == 1)
4697
4
    return true;
4698
29
  else if(inet_pton(AF_INET6, host, buf) == 1)
4699
0
    return true;
4700
29
  else
4701
29
    return false;
4702
33
}
4703
4704
/* **************************************** */
4705
4706
static u_int16_t ndpi_tls_refine_master_protocol(struct ndpi_detection_module_struct *ndpi_struct,
4707
39
             struct ndpi_flow_struct *flow) {
4708
39
  struct ndpi_packet_struct *packet = &ndpi_struct->packet;
4709
39
  u_int32_t protocol;
4710
4711
39
  if(packet->tcp != NULL) {
4712
    /*
4713
      In case of TLS there are probably sub-protocols
4714
      such as IMAPS that can be otherwise detected
4715
    */
4716
39
    u_int16_t sport = ntohs(packet->tcp->source);
4717
39
    u_int16_t dport = ntohs(packet->tcp->dest);
4718
4719
39
    if(flow->stun.maybe_dtls)
4720
0
      protocol = NDPI_PROTOCOL_DTLS;
4721
39
    else if((sport == 465) || (dport == 465) || (sport == 587) || (dport == 587))
4722
0
      protocol = NDPI_PROTOCOL_MAIL_SMTPS;
4723
39
    else if((sport == 993) || (dport == 993) || (flow->l4.tcp.mail_imap_starttls))
4724
0
      protocol = NDPI_PROTOCOL_MAIL_IMAPS;
4725
39
    else if((sport == 995) || (dport == 995))
4726
0
      protocol = NDPI_PROTOCOL_MAIL_POPS;
4727
39
    else
4728
39
      protocol = NDPI_PROTOCOL_TLS;
4729
39
  } else {
4730
0
      protocol = NDPI_PROTOCOL_DTLS;
4731
0
  }
4732
4733
39
  return protocol;
4734
39
}
4735
4736
/* **************************************** */
4737
4738
u_int16_t ndpi_get_master_proto(struct ndpi_detection_module_struct *ndpi_struct,
4739
42
        struct ndpi_flow_struct *flow) {
4740
42
  if(flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN)
4741
0
    return flow->detected_protocol_stack[1];
4742
42
  if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN)
4743
3
    return flow->detected_protocol_stack[0];
4744
4745
39
  return ndpi_tls_refine_master_protocol(ndpi_struct, flow);
4746
42
}
4747
4748
/* **************************************** */
4749
4750
char* ndpi_compute_ndpi_flow_fingerprint(struct ndpi_detection_module_struct *ndpi_str,
4751
700
           struct ndpi_flow_struct *flow) {
4752
700
  if(ndpi_str->cfg.ndpi_fingerprint_enabled &&
4753
639
     (flow->ndpi.fingerprint == NULL) &&
4754
639
     ndpi_stack_is_tls_like(&flow->protocol_stack) &&
4755
     /* We need TCP & TLS handshake. What should we do if we don't have them?
4756
        For the time being, keep calculating the fingerprint if we have at least
4757
        one of them. That means:
4758
          * we might have a fingerprint also for DTS/QUIC
4759
          * no fingerprint for mid-flows
4760
        TODO: is that what we really want? */
4761
9
     (flow->tcp.fingerprint || flow->protos.tls_quic.ja4_client[0] != '\0')) {
4762
0
    char *l4_fp = flow->tcp.fingerprint ? flow->tcp.fingerprint : "no_l4_fp";
4763
0
    char *l7_pf = "no_app_fp_cli";
4764
0
    char *l7_pf_server = "no_app_fp_srv";
4765
0
    u_int8_t sha_hash[NDPI_SHA256_BLOCK_SIZE];
4766
0
    size_t s;
4767
0
    u_int8_t fp_buf[128];
4768
4769
0
    if(flow->protos.tls_quic.ja4_client[0] != '\0')
4770
0
      l7_pf = flow->protos.tls_quic.ja4_client;
4771
4772
0
    if(ndpi_str->cfg.ndpi_fingerprint_format == NDPI_CLIENT_SERVER_NDPI_FINGERPRINT) {
4773
0
      if(flow->protos.tls_quic.sha1_certificate_fingerprint[0] != '\0')
4774
0
  l7_pf_server = (char*)flow->protos.tls_quic.sha1_certificate_fingerprint;
4775
0
      else {
4776
0
  if(flow->protos.tls_quic.ja3_server[0] != '\0')
4777
0
    l7_pf_server = flow->protos.tls_quic.ja3_server;
4778
0
      }
4779
0
    }
4780
4781
0
    s = snprintf((char*)fp_buf, sizeof(fp_buf)-1, "%s-%s-%s", l4_fp, l7_pf, l7_pf_server);
4782
0
    if(s > 0) {
4783
0
      s = ndpi_min(s, sizeof(fp_buf)-1);
4784
0
      ndpi_sha256(fp_buf, s, sha_hash);
4785
4786
0
      ndpi_snprintf((char*)fp_buf, sizeof(fp_buf),
4787
0
        "%02x%02x%02x%02x%02x%02x%02x%02x"
4788
0
        "%02x%02x%02x%02x%02x%02x%02x%02x",
4789
0
        sha_hash[0], sha_hash[1], sha_hash[2],    sha_hash[3],
4790
0
        sha_hash[4], sha_hash[5], sha_hash[6],    sha_hash[7],
4791
0
        sha_hash[8], sha_hash[9], sha_hash[10],   sha_hash[11],
4792
0
        sha_hash[12], sha_hash[13], sha_hash[14], sha_hash[15]
4793
0
        );
4794
4795
0
      flow->ndpi.fingerprint = ndpi_strdup((char*)fp_buf);
4796
4797
0
      if(flow->ndpi.fingerprint != NULL &&
4798
0
         ndpi_str->ndpifp_custom_protos != NULL) {
4799
0
  u_int64_t proto_id;
4800
4801
  /* This protocol has been defined in protos.txt-like files */
4802
0
  if(ndpi_hash_find_entry(ndpi_str->ndpifp_custom_protos,
4803
0
        flow->ndpi.fingerprint, strlen(flow->ndpi.fingerprint),
4804
0
        &proto_id) == 0) {
4805
0
    ndpi_set_detected_protocol(ndpi_str, flow, proto_id,
4806
0
             ndpi_get_master_proto(ndpi_str, flow),
4807
0
             NDPI_CONFIDENCE_CUSTOM_RULE);
4808
0
  }
4809
0
      }
4810
0
    }
4811
0
  }
4812
4813
700
  return(flow->ndpi.fingerprint);
4814
700
}
4815
4816
/* ****************************************** */
4817
4818
2.86k
void* ndpi_memmem(const void* haystack, size_t haystack_len, const void* needle, size_t needle_len) {
4819
2.86k
  if (!haystack || !needle || haystack_len < needle_len) {
4820
1.02k
    return NULL;
4821
1.02k
  }
4822
4823
1.83k
  if (needle_len == 0) {
4824
0
    return (void *)haystack;
4825
0
  }
4826
4827
1.83k
  if (needle_len == 1) {
4828
1.67k
    return (void *)memchr(haystack, *(const u_int8_t *)needle, haystack_len);
4829
1.67k
  }
4830
4831
160
  const u_int8_t *const end_of_search = (const u_int8_t *)haystack + haystack_len - needle_len + 1;
4832
4833
160
  const u_int8_t *current = (const u_int8_t *)haystack;
4834
4835
451
  while (1) {
4836
    /* Find the first occurrence of the first character from the needle */
4837
451
    current = (const u_int8_t *)memchr(current, *(const u_int8_t *)needle, end_of_search - current);
4838
4839
451
    if (!current) {
4840
143
      return NULL;
4841
143
    }
4842
4843
    /* Check the rest of the needle for a match */
4844
308
    if (memcmp(current, needle, needle_len) == 0) {
4845
17
      return (void *)current;
4846
17
    }
4847
4848
    /* Shift one character to the right for the next search */
4849
291
    current++;
4850
291
  }
4851
4852
0
  return NULL;
4853
160
}
4854
4855
/* ****************************************** */
4856
4857
0
size_t ndpi_strlcpy(char *dst, const char* src, size_t dst_len, size_t src_len) {
4858
0
  if (!dst || !src || dst_len == 0) {
4859
0
    return 0;
4860
0
  }
4861
4862
0
  size_t copy_len = ndpi_min(src_len, dst_len - 1);
4863
0
  memmove(dst, src, copy_len);
4864
0
  dst[copy_len] = '\0';
4865
4866
0
  return src_len;
4867
0
}
4868
4869
/* ****************************************** */
4870
4871
20.4k
int ndpi_memcasecmp(const void *s1, const void *s2, size_t n) {
4872
20.4k
  if (s1 == NULL && s2 == NULL) {
4873
0
    return 0;
4874
0
  }
4875
4876
20.4k
  if (s1 == NULL) {
4877
0
    return -1;
4878
0
  }
4879
4880
20.4k
  if (s2 == NULL) {
4881
0
    return 1;
4882
0
  }
4883
4884
20.4k
  if (n == 0) {
4885
0
    return 0;
4886
0
  }
4887
4888
20.4k
  const unsigned char *p1 = (const unsigned char *)s1;
4889
20.4k
  const unsigned char *p2 = (const unsigned char *)s2;
4890
4891
20.4k
  if (n == 1) {
4892
0
    return tolower(*p1) - tolower(*p2);
4893
0
  }
4894
4895
  /* Early exit optimization - check first and last bytes */
4896
4897
20.4k
  int first_cmp = tolower(p1[0]) - tolower(p2[0]);
4898
20.4k
  if (first_cmp != 0) {
4899
19.6k
    return first_cmp;
4900
19.6k
  }
4901
4902
743
  int last_cmp = tolower(p1[n-1]) - tolower(p2[n-1]);
4903
743
  if (last_cmp != 0) {
4904
675
    return last_cmp;
4905
675
  }
4906
4907
68
  size_t i;
4908
260
  for (i = 1; i < n-1; i++) {
4909
196
    int cmp = tolower(p1[i]) - tolower(p2[i]);
4910
196
    if (cmp != 0) {
4911
4
      return cmp;
4912
4
    }
4913
196
  }
4914
4915
64
  return 0;
4916
68
}
4917
4918
/* ****************************************** */
4919
4920
char *ndpi_stack2str(struct ndpi_detection_module_struct *ndpi_str,
4921
765
                     struct ndpi_proto_stack *stack, char *buf, u_int buf_len) {
4922
765
  int ret, used = 0, i = 0;
4923
4924
765
  if(!ndpi_str || buf == NULL || buf_len == 0)
4925
49
    return NULL;
4926
4927
716
  buf[0] = '\0';
4928
4929
716
  if(stack->protos_num == 0) {
4930
272
    ndpi_snprintf(buf, buf_len, "Unknown");
4931
272
    return buf;
4932
272
  }
4933
4934
935
  while((int64_t)buf_len - used > 0 && i < stack->protos_num) {
4935
491
    ret = ndpi_snprintf(buf + used, buf_len - used, "%s%s",
4936
491
                       i != 0 ? "." : "",
4937
491
                      ndpi_get_proto_name(ndpi_str, stack->protos[i]));
4938
491
    if(ret <= 0)
4939
0
      break;
4940
491
    used += ret;
4941
491
    i++;
4942
491
  }
4943
4944
444
  return buf;
4945
716
}