/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 | } |