]> git.ipfire.org Git - thirdparty/snort3.git/blob - src/network_inspectors/appid/app_info_table.cc
Pull request #4257: appid: enhanced appid config parsing
[thirdparty/snort3.git] / src / network_inspectors / appid / app_info_table.cc
1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2024 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2005-2013 Sourcefire, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation. You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 //--------------------------------------------------------------------------
19
20 // app_info_table.cc author Sourcefire Inc.
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "app_info_table.h"
27
28 #include <climits>
29 #include <fstream>
30 #include <string>
31 #include <unistd.h>
32
33 #include "log/messages.h"
34 #include "log/unified2.h"
35 #include "main/snort_config.h"
36 #include "target_based/snort_protocols.h"
37 #include "utils/util_cstring.h"
38
39 #include "appid_api.h"
40 #include "appid_config.h"
41 #include "appid_debug.h"
42 #include "appid_inspector.h"
43 #include "appid_peg_counts.h"
44
45 using namespace snort;
46
47 #define MAX_TABLE_LINE_LEN 1024
48 static const int MIN_MAX_TP_FLOW_DEPTH = 1;
49 static const int MAX_MAX_TP_FLOW_DEPTH = 1000000;
50 static const int MIN_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL = 1;
51 static const int MAX_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL = 1000000;
52 static const int MIN_HOST_PORT_APP_CACHE_LOOKUP_RANGE = 1;
53 static const int MAX_HOST_PORT_APP_CACHE_LOOKUP_RANGE = 1000000;
54 static const char* APP_CONFIG_FILE = "appid.conf";
55 static const char* USR_CONFIG_FILE = "userappid.conf";
56 const char* APP_MAPPING_FILE = "appMapping.data";
57
58 AppInfoTableEntry::AppInfoTableEntry(AppId id, char* name)
59 : appId(id), serviceId(id), clientId(id), payloadId(id), app_name(name)
60 {
61 app_name_key = AppInfoManager::strdup_to_lower(name);
62 }
63
64 AppInfoTableEntry::AppInfoTableEntry(AppId id, char* name, AppId sid, AppId cid, AppId pid) :
65 appId(id), serviceId(sid), clientId(cid), payloadId(pid), app_name(name)
66 {
67 app_name_key = AppInfoManager::strdup_to_lower(name);
68 }
69
70 AppInfoTableEntry::~AppInfoTableEntry()
71 {
72 if (app_name)
73 snort_free(app_name);
74 if (app_name_key)
75 snort_free(app_name_key);
76 }
77
78 bool AppInfoManager::is_existing_entry(AppInfoTableEntry* entry)
79 {
80 AppInfoNameTable::iterator app;
81
82 app = app_info_name_table.find(entry->app_name_key);
83 return app != app_info_name_table.end();
84 }
85
86 AppInfoTableEntry* AppInfoManager::find_app_info_by_name(const char* app_name)
87 {
88 AppInfoTableEntry* entry = nullptr;
89 AppInfoNameTable::iterator app;
90 const char* search_name = AppInfoManager::strdup_to_lower(app_name);
91
92 app = app_info_name_table.find(search_name);
93 if (app != app_info_name_table.end())
94 entry = app->second;
95
96 snort_free((void*)search_name);
97 return entry;
98 }
99
100 bool AppInfoManager::add_entry_to_app_info_name_table(const char* app_name,
101 AppInfoTableEntry* entry)
102 {
103 bool added = true;
104
105 if (!is_existing_entry(entry))
106 app_info_name_table[app_name] = entry;
107 else
108 {
109 appid_log(nullptr, TRACE_WARNING_LEVEL, "App name, \"%s\" is a duplicate entry will be shared by "
110 "each detector.\n", app_name);
111 added = false;
112 }
113 return added;
114 }
115
116 AppId AppInfoManager::get_static_app_info_entry(AppId appid)
117 {
118 if (appid > 0 && appid < SF_APPID_BUILDIN_MAX)
119 return appid;
120 if ((appid >= SF_APPID_CSD_MIN) &&
121 appid < (SF_APPID_CSD_MIN + (SF_APPID_MAX - SF_APPID_BUILDIN_MAX)))
122 return (SF_APPID_BUILDIN_MAX + appid - SF_APPID_CSD_MIN);
123 return 0;
124 }
125
126 char* AppInfoManager::strdup_to_lower(const char* source)
127 {
128 char* dest = snort_strdup(source);
129 char* lcd = dest;
130
131 while (*lcd)
132 {
133 *lcd = tolower(*lcd);
134 lcd++;
135 }
136 return dest;
137 }
138
139 bool AppInfoManager::configured()
140 {
141 return !app_info_table.empty();
142 }
143
144 AppInfoTableEntry* AppInfoManager::get_app_info_entry(AppId appId,
145 const AppInfoTable& lookup_table)
146 {
147 AppId tmp;
148 AppInfoTable::const_iterator app;
149 AppInfoTableEntry* entry = nullptr;
150
151 if ((tmp = get_static_app_info_entry(appId)))
152 {
153 app = lookup_table.find(tmp);
154 if (app != lookup_table.end())
155 entry = app->second;
156 }
157 else
158 {
159 app = custom_app_info_table.find(appId);
160 if (app != custom_app_info_table.end())
161 entry = app->second;
162 }
163 return entry;
164 }
165
166 AppInfoTableEntry* AppInfoManager::get_app_info_entry(AppId appId)
167 {
168 return get_app_info_entry(appId, app_info_table);
169 }
170
171 AppInfoTableEntry* AppInfoManager::add_dynamic_app_entry(const char* app_name)
172 {
173 if (!app_name || strlen(app_name) >= MAX_EVENT_APPNAME_LEN)
174 {
175 appid_log(nullptr, TRACE_ERROR_LEVEL, "Appname invalid or too long: %s\n", app_name);
176 return nullptr;
177 }
178
179 AppInfoTableEntry* entry = find_app_info_by_name(app_name);
180 if (!entry)
181 {
182 entry = new AppInfoTableEntry(next_custom_appid++, snort_strdup(app_name));
183 custom_app_info_table[entry->appId] = entry;
184
185 if (!add_entry_to_app_info_name_table(entry->app_name_key, entry))
186 {
187 delete entry;
188 return nullptr;
189 }
190 }
191 return entry;
192 }
193
194 void AppInfoManager::cleanup_appid_info_table()
195 {
196 for (const auto& kv: app_info_table)
197 delete(kv.second);
198 app_info_table.erase(app_info_table.begin(), app_info_table.end());
199
200 for (const auto& kv: custom_app_info_table)
201 delete(kv.second);
202
203 custom_app_info_table.erase(custom_app_info_table.begin(), custom_app_info_table.end());
204 app_info_name_table.erase(app_info_name_table.begin(), app_info_name_table.end());
205 }
206
207 void AppInfoManager::dump_app_info_table()
208 {
209 appid_log(nullptr, TRACE_INFO_LEVEL, "Cisco provided detectors:\n");
210 for (auto& kv: app_info_table)
211 appid_log(nullptr, TRACE_INFO_LEVEL, "%s\t%d\t%s\n", kv.second->app_name, kv.second->appId,
212 (kv.second->flags & APPINFO_FLAG_ACTIVE) ? "active" : "inactive");
213
214 appid_log(nullptr, TRACE_INFO_LEVEL, "User provided detectors:\n");
215 for (auto& kv: custom_app_info_table)
216 appid_log(nullptr, TRACE_INFO_LEVEL, "%s\t%d\t%s\n", kv.second->app_name, kv.second->appId,
217 (kv.second->flags & APPINFO_FLAG_ACTIVE) ? "active" : "inactive");
218 }
219
220 AppId AppInfoManager::get_appid_by_service_id(uint32_t id)
221 {
222 AppInfoTableEntry* entry = get_app_info_entry(id, app_info_service_table);
223 return entry ? entry->appId : APP_ID_NONE;
224 }
225
226 AppId AppInfoManager::get_appid_by_client_id(uint32_t id)
227 {
228 AppInfoTableEntry* entry = get_app_info_entry(id, app_info_client_table);
229 return entry ? entry->appId : APP_ID_NONE;
230 }
231
232 AppId AppInfoManager::get_appid_by_payload_id(uint32_t id)
233 {
234 AppInfoTableEntry* entry = get_app_info_entry(id, app_info_payload_table);
235 return entry ? entry->appId : APP_ID_NONE;
236 }
237
238 const char* AppInfoManager::get_app_name(int32_t id)
239 {
240 AppInfoTableEntry* entry = get_app_info_entry(id);
241 return entry ? entry->app_name : nullptr;
242 }
243
244 const char* AppInfoManager::get_app_name_key(int32_t id)
245 {
246 AppInfoTableEntry* entry = get_app_info_entry(id);
247 return entry ? entry->app_name_key : nullptr;
248 }
249
250 AppId AppInfoManager::get_appid_by_name(const char* app_name)
251 {
252 AppInfoTableEntry* entry = find_app_info_by_name(app_name);
253 return entry ? entry->appId : APP_ID_NONE;
254 }
255
256 void AppInfoManager::set_app_info_active(AppId appId)
257 {
258 if (appId == APP_ID_NONE)
259 return;
260
261 AppInfoTableEntry* entry = get_app_info_entry(appId);
262 if (entry)
263 entry->flags |= APPINFO_FLAG_ACTIVE;
264 else
265 ParseWarning(WARN_PLUGINS, "appid: no entry in %s for %d", APP_MAPPING_FILE, appId);
266 }
267
268 void AppInfoManager::load_odp_config(OdpContext& odp_ctxt, const char* path)
269 {
270 char buf[MAX_TABLE_LINE_LEN];
271 unsigned line = 0;
272 const char* CONF_SEPARATORS = "\t\n\r ";
273
274 FILE* config_file = fopen(path, "r");
275 if (config_file == nullptr)
276 return;
277
278 while (fgets(buf, sizeof(buf), config_file) != nullptr)
279 {
280 char* context;
281
282 line++;
283 char* token = strtok_r(buf, CONF_SEPARATORS, &context);
284 if (token == nullptr)
285 {
286 ParseWarning(WARN_CONF, "appid: No 'conf_type' value at line %s:%u\n", path, line);
287 continue;
288 }
289 char* conf_type = token;
290
291 token = strtok_r(nullptr, CONF_SEPARATORS, &context);
292 if (token == nullptr)
293 {
294 ParseWarning(WARN_CONF, "appid: No 'conf_key' value at line %s:%u\n", path, line);
295 continue;
296 }
297 char* conf_key = token;
298
299 token = strtok_r(nullptr, CONF_SEPARATORS, &context);
300 if (token == nullptr)
301 {
302 ParseWarning(WARN_CONF, "appid: No 'conf_val' value at line %s:%u\n", path, line);
303 continue;
304 }
305 char* conf_val = token;
306
307 /* APPID configurations are for anything else - currently we only have ssl_reinspect */
308 if (!(strcasecmp(conf_type, "appid")))
309 {
310 if (!(strcasecmp(conf_key, "max_tp_flow_depth")))
311 {
312 int max_tp_flow_depth = atoi(conf_val);
313 if (max_tp_flow_depth < MIN_MAX_TP_FLOW_DEPTH
314 || max_tp_flow_depth > MAX_MAX_TP_FLOW_DEPTH)
315 {
316 ParseWarning(WARN_CONF,
317 "appid: invalid max_tp_flow_depth %d, must be between %d and %d\n.",
318 max_tp_flow_depth, MIN_MAX_TP_FLOW_DEPTH, MAX_MAX_TP_FLOW_DEPTH);
319 }
320 else
321 {
322 odp_ctxt.max_tp_flow_depth = max_tp_flow_depth;
323 }
324 }
325 else if (!(strcasecmp(conf_key, "host_port_app_cache_lookup_interval")))
326 {
327 int host_port_app_cache_lookup_interval = atoi(conf_val);
328 if (host_port_app_cache_lookup_interval <
329 MIN_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL ||
330 host_port_app_cache_lookup_interval >
331 MAX_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL)
332 {
333 ParseWarning(WARN_CONF,
334 "appid: invalid host_port_app_cache_lookup_interval %d, "
335 "must be between %d and %d\n.",
336 host_port_app_cache_lookup_interval,
337 MIN_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL,
338 MAX_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL);
339 }
340 else
341 {
342 odp_ctxt.host_port_app_cache_lookup_interval =
343 host_port_app_cache_lookup_interval;
344 }
345 }
346 else if (!(strcasecmp(conf_key, "host_port_app_cache_lookup_range")))
347 {
348 int host_port_app_cache_lookup_range = atoi(conf_val);
349 if (host_port_app_cache_lookup_range < MIN_HOST_PORT_APP_CACHE_LOOKUP_RANGE
350 || host_port_app_cache_lookup_range > MAX_HOST_PORT_APP_CACHE_LOOKUP_RANGE)
351 {
352 ParseWarning(WARN_CONF,
353 "appid: invalid host_port_app_cache_lookup_range %d, "
354 "must be between %d and %d\n.", host_port_app_cache_lookup_range,
355 MIN_HOST_PORT_APP_CACHE_LOOKUP_RANGE,
356 MAX_HOST_PORT_APP_CACHE_LOOKUP_RANGE);
357 }
358 else
359 {
360 odp_ctxt.host_port_app_cache_lookup_range = host_port_app_cache_lookup_range;
361 }
362 }
363 else if (!(strcasecmp(conf_key, "is_host_port_app_cache_runtime")))
364 {
365 if (!(strcasecmp(conf_val, "enabled")))
366 {
367 odp_ctxt.is_host_port_app_cache_runtime = true;
368 }
369 }
370 else if (!(strcasecmp(conf_key, "check_host_port_app_cache")))
371 {
372 if (!(strcasecmp(conf_val, "enabled")))
373 {
374 odp_ctxt.check_host_port_app_cache = true;
375 }
376 }
377 else if (!(strcasecmp(conf_key, "check_host_cache_unknown_ssl")))
378 {
379 if (!(strcasecmp(conf_val, "enabled")))
380 {
381 odp_ctxt.check_host_cache_unknown_ssl = true;
382 }
383 }
384 else if (!(strcasecmp(conf_key, "allow_port_wildcard_host_cache")))
385 {
386 if (!(strcasecmp(conf_val, "enabled")))
387 {
388 odp_ctxt.allow_port_wildcard_host_cache = true;
389 }
390 }
391 else if (!(strcasecmp(conf_key, "recheck_for_portservice_appid")))
392 {
393 if (!(strcasecmp(conf_val, "enabled")))
394 {
395 odp_ctxt.recheck_for_portservice_appid = true;
396 }
397 }
398 else if (!(strcasecmp(conf_key, "bittorrent_aggressiveness")))
399 {
400 int aggressiveness = atoi(conf_val);
401 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: bittorrent_aggressiveness %d\n", aggressiveness);
402 if (aggressiveness >= 50)
403 {
404 odp_ctxt.host_port_app_cache_lookup_interval = 5;
405 odp_ctxt.recheck_for_portservice_appid = true;
406 set_app_info_flags(APP_ID_BITTORRENT, APPINFO_FLAG_DEFER);
407 set_app_info_flags(APP_ID_BITTORRENT, APPINFO_FLAG_DEFER_PAYLOAD);
408 odp_ctxt.max_tp_flow_depth = 25;
409 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: host_port_app_cache_lookup_interval %d\n",
410 odp_ctxt.host_port_app_cache_lookup_interval);
411 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: recheck_for_portservice_appid enabled\n");
412 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: defer_to_thirdparty %d\n", APP_ID_BITTORRENT);
413 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: defer_payload_to_thirdparty %d\n", APP_ID_BITTORRENT);
414 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: max_tp_flow_depth %d\n", odp_ctxt.max_tp_flow_depth);
415 }
416 if (aggressiveness >= 80)
417 {
418 odp_ctxt.allow_port_wildcard_host_cache = true;
419 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: allow_port_wildcard_host_cache enabled\n");
420 }
421 }
422 else if (!(strcasecmp(conf_key, "ultrasurf_aggressiveness")))
423 {
424 int aggressiveness = atoi(conf_val);
425 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: ultrasurf_aggressiveness %d\n", aggressiveness);
426 if (aggressiveness >= 50)
427 {
428 odp_ctxt.check_host_cache_unknown_ssl = true;
429 set_app_info_flags(APP_ID_ULTRASURF, APPINFO_FLAG_DEFER);
430 set_app_info_flags(APP_ID_ULTRASURF, APPINFO_FLAG_DEFER_PAYLOAD);
431 odp_ctxt.max_tp_flow_depth = 25;
432 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: check_host_cache_unknown_ssl enabled\n");
433 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: defer_to_thirdparty %d\n", APP_ID_ULTRASURF);
434 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: defer_payload_to_thirdparty %d\n", APP_ID_ULTRASURF);
435 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: max_tp_flow_depth %d\n", odp_ctxt.max_tp_flow_depth);
436 }
437 if (aggressiveness >= 80)
438 {
439 odp_ctxt.allow_port_wildcard_host_cache = true;
440 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: allow_port_wildcard_host_cache enabled\n");
441 }
442 }
443 else if (!(strcasecmp(conf_key, "psiphon_aggressiveness")))
444 {
445 int aggressiveness = atoi(conf_val);
446 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: psiphon_aggressiveness %d\n", aggressiveness);
447 if (aggressiveness >= 50)
448 {
449 odp_ctxt.check_host_cache_unknown_ssl = true;
450 set_app_info_flags(APP_ID_PSIPHON, APPINFO_FLAG_DEFER);
451 set_app_info_flags(APP_ID_PSIPHON, APPINFO_FLAG_DEFER_PAYLOAD);
452 odp_ctxt.max_tp_flow_depth = 25;
453 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: check_host_cache_unknown_ssl enabled\n");
454 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: defer_to_thirdparty %d\n", APP_ID_PSIPHON);
455 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: defer_payload_to_thirdparty %d\n", APP_ID_PSIPHON);
456 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: max_tp_flow_depth %d\n", odp_ctxt.max_tp_flow_depth);
457 }
458 if (aggressiveness >= 80)
459 {
460 odp_ctxt.allow_port_wildcard_host_cache = true;
461 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: allow_port_wildcard_host_cache enabled\n");
462 }
463 }
464 else if (!(strcasecmp(conf_key, "tp_allow_probes")))
465 {
466 if (!(strcasecmp(conf_val, "enabled")))
467 {
468 odp_ctxt.tp_allow_probes = true;
469 }
470 }
471 else if (!(strcasecmp(conf_key, "tp_client_app")))
472 {
473 set_app_info_flags(atoi(conf_val), APPINFO_FLAG_TP_CLIENT);
474 }
475 else if (!(strcasecmp(conf_key, "ssl_reinspect")))
476 {
477 set_app_info_flags(atoi(conf_val), APPINFO_FLAG_SSL_INSPECT);
478 }
479 else if (!(strcasecmp(conf_key, "defer_to_thirdparty")))
480 {
481 set_app_info_flags(atoi(conf_val), APPINFO_FLAG_DEFER);
482 }
483 else if (!(strcasecmp(conf_key, "defer_payload_to_thirdparty")))
484 {
485 set_app_info_flags(atoi(conf_val), APPINFO_FLAG_DEFER_PAYLOAD);
486 }
487 else if (!(strcasecmp(conf_key, "chp_userid")))
488 {
489 if (!(strcasecmp(conf_val, "disabled")))
490 {
491 odp_ctxt.chp_userid_disabled = true;
492 continue;
493 }
494 }
495 else if (!(strcasecmp(conf_key, "chp_body_collection")))
496 {
497 if (!(strcasecmp(conf_val, "disabled")))
498 {
499 odp_ctxt.chp_body_collection_disabled = true;
500 continue;
501 }
502 }
503 else if (!(strcasecmp(conf_key, "ftp_userid")))
504 {
505 if (!(strcasecmp(conf_val, "disabled")))
506 {
507 odp_ctxt.ftp_userid_disabled = true;
508 continue;
509 }
510 }
511 else if (!(strcasecmp(conf_key, "max_bytes_before_service_fail")))
512 {
513 uint64_t max_bytes_before_service_fail = atoi(conf_val);
514 if (max_bytes_before_service_fail < MIN_MAX_BYTES_BEFORE_SERVICE_FAIL)
515 {
516 appid_log(nullptr, TRACE_WARNING_LEVEL, "appid: invalid max_bytes_before_service_fail "
517 "%" PRIu64 " must be greater than %u.\n", max_bytes_before_service_fail,
518 MIN_MAX_BYTES_BEFORE_SERVICE_FAIL);
519 }
520 else
521 {
522 odp_ctxt.max_bytes_before_service_fail = max_bytes_before_service_fail;
523 }
524 }
525 else if (!(strcasecmp(conf_key, "max_packet_before_service_fail")))
526 {
527 uint16_t max_packet_before_service_fail = atoi(conf_val);
528 if (max_packet_before_service_fail < MIN_MAX_PKTS_BEFORE_SERVICE_FAIL)
529 {
530 appid_log(nullptr, TRACE_WARNING_LEVEL, "appid: invalid max_packet_before_service_fail "
531 "%" PRIu16 ", must be greater than %u.\n", max_packet_before_service_fail,
532 MIN_MAX_PKTS_BEFORE_SERVICE_FAIL);
533 }
534 else
535 {
536 odp_ctxt.max_packet_before_service_fail = max_packet_before_service_fail;
537 }
538 }
539 else if (!(strcasecmp(conf_key, "max_packet_service_fail_ignore_bytes")))
540 {
541 uint16_t max_packet_service_fail_ignore_bytes = atoi(conf_val);
542 if (max_packet_service_fail_ignore_bytes <
543 MIN_MAX_PKT_BEFORE_SERVICE_FAIL_IGNORE_BYTES)
544 {
545 appid_log(nullptr, TRACE_WARNING_LEVEL, "appid: invalid max_packet_service_fail_ignore_bytes"
546 "%" PRIu16 ", must be greater than %u.\n",
547 max_packet_service_fail_ignore_bytes,
548 MIN_MAX_PKT_BEFORE_SERVICE_FAIL_IGNORE_BYTES);
549 }
550 else
551 {
552 odp_ctxt.max_packet_service_fail_ignore_bytes =
553 max_packet_service_fail_ignore_bytes;
554 }
555 }
556 /* App Priority bit set*/
557 else if (!(strcasecmp(conf_key, "app_priority")))
558 {
559 int temp_appid;
560 temp_appid = strtol(conf_val, nullptr, 10);
561 token = strtok_r(nullptr, CONF_SEPARATORS, &context);
562 if (token == nullptr)
563 {
564 ParseWarning(WARN_CONF, "appid: Could not read app_priority at line %u\n", line);
565 continue;
566 }
567 conf_val = token;
568 uint8_t temp_val;
569 temp_val = strtol(conf_val, nullptr, 10);
570 set_app_info_priority (temp_appid, temp_val);
571 }
572 else if (!(strcasecmp(conf_key, "referred_appId")))
573 {
574 if (!(strcasecmp(conf_val, "disabled")))
575 {
576 odp_ctxt.referred_appId_disabled = true;
577 continue;
578 }
579 else if (!odp_ctxt.referred_appId_disabled)
580 {
581 char referred_app_list[4096];
582 int referred_app_index = safe_snprintf(referred_app_list, 4096, "%d ",
583 atoi(conf_val));
584 set_app_info_flags(atoi(conf_val), APPINFO_FLAG_REFERRED);
585
586 while ((token = strtok_r(nullptr, CONF_SEPARATORS, &context)) != nullptr)
587 {
588 AppId id = atoi(token);
589 referred_app_index += safe_snprintf(referred_app_list + referred_app_index,
590 sizeof(referred_app_list) - referred_app_index, "%d ", id);
591 set_app_info_flags(id, APPINFO_FLAG_REFERRED);
592 }
593 }
594 }
595 else if (!(strcasecmp(conf_key, "rtmp_max_packets")))
596 {
597 odp_ctxt.rtmp_max_packets = atoi(conf_val);
598 }
599 else if (!(strcasecmp(conf_key, "mdns_user_report")))
600 {
601 odp_ctxt.mdns_user_reporting = atoi(conf_val) ? true : false;
602 }
603 else if (!(strcasecmp(conf_key, "dns_host_report")))
604 {
605 odp_ctxt.dns_host_reporting = atoi(conf_val) ? true : false;
606 }
607 else if (!(strcasecmp(conf_key, "chp_body_max_bytes")))
608 {
609 odp_ctxt.chp_body_collection_max = atoi(conf_val);
610 }
611 else if (!(strcasecmp(conf_key, "ignore_thirdparty_appid")))
612 {
613 set_app_info_flags(atoi(conf_val), APPINFO_FLAG_IGNORE);
614 }
615 else if (!(strcasecmp(conf_key, "eve_http_client")))
616 {
617 odp_ctxt.eve_http_client = atoi(conf_val) ? true : false;
618 }
619 else
620 ParseWarning(WARN_CONF, "appid: unsupported configuration: %s\n", conf_key);
621 }
622 }
623
624 fclose(config_file);
625 }
626
627 void AppInfoManager::dump_appid_configurations(const std::string& file_path) const
628 {
629 std::ifstream conf_file(file_path);
630 if (!conf_file.is_open())
631 return;
632
633 appid_log(nullptr, TRACE_INFO_LEVEL, "AppId: Configuration file %s\n", file_path.c_str());
634 std::string line;
635 while (getline(conf_file, line))
636 appid_log(nullptr, TRACE_INFO_LEVEL, "%s\n", line.c_str());
637
638 conf_file.close();
639 }
640
641 SnortProtocolId AppInfoManager::add_appid_protocol_reference(const char* protocol,
642 SnortConfig* sc)
643 {
644 SnortProtocolId snort_protocol_id = sc->proto_ref->add(protocol);
645 return snort_protocol_id;
646 }
647
648 void AppInfoManager::init_appid_info_table(const AppIdConfig& config,
649 SnortConfig* sc, OdpContext& odp_ctxt)
650 {
651 if (!config.app_detector_dir)
652 {
653 return; // no lua detectors, no rule support, already warned
654 }
655
656 char filepath[PATH_MAX];
657 snprintf(filepath, sizeof(filepath), "%s/odp/%s", config.app_detector_dir,
658 APP_MAPPING_FILE);
659
660 FILE* tableFile = fopen(filepath, "r");
661
662 if (!tableFile)
663 {
664 ParseError("appid: could not open %s", filepath);
665 }
666 else
667 {
668 char buf[MAX_TABLE_LINE_LEN];
669 const char* CONF_SEPARATORS = "\t\n\r";
670 while (fgets(buf, sizeof(buf), tableFile))
671 {
672 AppId app_id;
673 uint32_t client_id, service_id, payload_id;
674 char* app_name;
675 char* context;
676
677 const char* token = strtok_r(buf, CONF_SEPARATORS, &context);
678 if (!token)
679 {
680 appid_log(nullptr, TRACE_ERROR_LEVEL, "Could not read id for AppId\n");
681 continue;
682 }
683 app_id = strtol(token, nullptr, 10);
684
685 token = strtok_r(nullptr, CONF_SEPARATORS, &context);
686 if (!token)
687 {
688 appid_log(nullptr, TRACE_ERROR_LEVEL, "Could not read app_name. Line %s\n", buf);
689 continue;
690 }
691 app_name = snort_strdup(token);
692
693 token = strtok_r(nullptr, CONF_SEPARATORS, &context);
694 if (!token)
695 {
696 appid_log(nullptr, TRACE_ERROR_LEVEL, "Could not read service id for AppId\n");
697 snort_free(app_name);
698 continue;
699 }
700 service_id = strtoul(token, nullptr, 10);
701
702 token = strtok_r(nullptr, CONF_SEPARATORS, &context);
703 if (!token)
704 {
705 appid_log(nullptr, TRACE_ERROR_LEVEL, "Could not read client id for AppId\n");
706 snort_free(app_name);
707 continue;
708 }
709 client_id = strtoul(token, nullptr, 10);
710
711 token = strtok_r(nullptr, CONF_SEPARATORS, &context);
712 if (!token)
713 {
714 appid_log(nullptr, TRACE_ERROR_LEVEL, "Could not read payload id for AppId\n");
715 snort_free(app_name);
716 continue;
717 }
718 payload_id = strtoul(token, nullptr, 10);
719
720 AppInfoTableEntry* entry = new AppInfoTableEntry(app_id, app_name, service_id,
721 client_id, payload_id);
722
723 /* snort service key, if it exists */
724 token = strtok_r(nullptr, CONF_SEPARATORS, &context);
725
726 // FIXIT-RC: Sometimes the token is "~". Should we ignore those?
727 if (token)
728 entry->snort_protocol_id = add_appid_protocol_reference(token, sc);
729
730 if (!add_entry_to_app_info_name_table(entry->app_name_key, entry))
731 delete entry;
732 else
733 {
734 if ((app_id = get_static_app_info_entry(entry->appId)))
735 {
736 app_info_table[app_id] = entry;
737 AppIdPegCounts::add_app_peg_info(entry->app_name_key, app_id);
738 }
739 if ((app_id = get_static_app_info_entry(entry->serviceId)))
740 app_info_service_table[app_id] = entry;
741 if ((app_id = get_static_app_info_entry(entry->clientId)))
742 app_info_client_table[app_id] = entry;
743 if ((app_id = get_static_app_info_entry(entry->payloadId)))
744 app_info_payload_table[app_id] = entry;
745 }
746 }
747 fclose(tableFile);
748
749 snprintf(filepath, sizeof(filepath), "%s/odp/%s", config.app_detector_dir,
750 APP_CONFIG_FILE);
751 load_odp_config(odp_ctxt, filepath);
752 snprintf(filepath, sizeof(filepath), "%s/custom/%s", config.app_detector_dir,
753 USR_CONFIG_FILE);
754 if (access (filepath, F_OK))
755 snprintf(filepath, sizeof(filepath), "%s/../%s", config.app_detector_dir,
756 USR_CONFIG_FILE);
757 load_odp_config(odp_ctxt, filepath);
758 }
759 }
760