"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/dynamic-preprocessors/appid/spp_appid.c" (16 Oct 2020, 16406 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "spp_appid.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.9.16.1_vs_2.9.17.
1 /*
2 ** Copyright (C) 2014-2020 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
6 ** it under the terms of the GNU General Public License Version 2 as
7 ** published by the Free Software Foundation. You may not use, modify or
8 ** distribute this program under any other version of the GNU General
9 ** Public License.
10 **
11 ** This program 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 General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 #include <stdint.h>
22 #include <stdbool.h>
23 #include <strings.h>
24 #include <stdio.h>
25 #include <syslog.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <inttypes.h>
30 #include <sys/time.h>
31 #include <pthread.h>
32
33 #include "sf_snort_packet.h"
34 #include "sf_dynamic_preprocessor.h"
35 #include "common_util.h"
36 #include "sf_preproc_info.h"
37
38 #include "spp_appid.h"
39 #include "fw_appid.h"
40 #include "flow.h"
41 #include "service_base.h"
42 #include "luaDetectorModule.h"
43 #include "appIdConfig.h"
44 #include "appIdStats.h"
45 #ifdef SIDE_CHANNEL
46 #include "appId_ss.h"
47 #endif
48 #include "appInfoTable.h"
49 #include "thirdparty_appid_utils.h"
50
51 #include "cip_common.h"
52 #include "detector_cip.h"
53
54 #ifdef PERF_PROFILING
55 PreprocStats appMatchPerfStats;
56 #endif
57
58 const int MAJOR_VERSION = 1;
59 const int MINOR_VERSION = 1;
60 const int BUILD_VERSION = 5;
61
62 static uint16_t appid_preproc_status_bit = 0;
63
64
65 SF_SO_PUBLIC const char *PREPROC_NAME = "appid";
66
67 static pthread_mutex_t appIdReloadMutex = PTHREAD_MUTEX_INITIALIZER;
68 static bool appIdReloadInProgress = false;
69
70 extern void appIdApiInit(struct AppIdApi*);
71
72 static void AppIdProcess(SFSnortPacket *p, void *context)
73 {
74 PROFILE_VARS;
75 PREPROC_PROFILE_START(appMatchPerfStats);
76 /* Trust */
77 if (p->stream_session && _dpd.sessionAPI->get_ignore_direction(p->stream_session) == SSN_DIR_BOTH)
78 {
79 _dpd.sessionAPI->disable_preproc_for_session( p->stream_session, PP_NETWORK_DISCOVERY );
80 PREPROC_PROFILE_END(appMatchPerfStats);
81 return;
82 }
83 fwAppIdSearch(p);
84 PREPROC_PROFILE_END(appMatchPerfStats);
85 }
86
87 static void AppIdAddPortsToStream5Filter(struct _SnortConfig *sc, tSfPolicyId policy_id)
88 {
89 unsigned portNum;
90
91 for (portNum = 0; portNum < 65536; portNum++)
92 {
93 /*Add port the port */
94 _dpd.streamAPI->set_port_filter_status(sc, IPPROTO_TCP, (uint16_t)portNum,
95 appid_preproc_status_bit, policy_id, 1);
96 _dpd.streamAPI->set_port_filter_status(sc, IPPROTO_UDP, (uint16_t)portNum,
97 appid_preproc_status_bit, policy_id, 1);
98 }
99 }
100
101 static void initializeAppIDForDispatch(struct _SnortConfig *sc)
102 {
103 _dpd.sessionAPI->enable_preproc_all_ports_all_policies(sc, PP_APP_ID, PROTO_BIT__IP);
104 _dpd.addPreprocAllPolicies(sc, (void (*)(void *, void *))AppIdProcess, PRIORITY_TRANSPORT + 1,
105 PP_APP_ID, PROTO_BIT__IP);
106 }
107
108 static int AppIDCheckConfig(struct _SnortConfig *sc)
109 {
110 initializeAppIDForDispatch(sc);
111 return 0;
112 }
113
114 static void AppIdStaticConfigFree(tAppidStaticConfig* appidSC)
115 {
116 if (appidSC)
117 {
118 free((char *)(appidSC->appid_thirdparty_dir));
119 free(appidSC->tp_config_path);
120 free(appidSC->app_id_detector_path);
121 free(appidSC->conf_file);
122 free(appidSC->app_stats_filename);
123 #ifdef SIDE_CHANNEL
124 if (appidSC->appId_ss_config)
125 AppIdSSConfigFree(appidSC->appId_ss_config);
126 #endif
127 if (appidSC->newAppIdConfig)
128 AppIdCommonUnload(appidSC->newAppIdConfig);
129
130 free(appidSC);
131 }
132 }
133
134 #ifdef SNORT_RELOAD
135
136 /********** AppId Reload Functions **********/
137
138 static void reloadWait(void)
139 {
140 const struct timespec reloadPollTime = {0, 1000000}; // 1 msec wait time to poll reload status
141
142 for (;;)
143 {
144 pthread_mutex_lock(&appIdReloadMutex);
145 if (!appIdReloadInProgress)
146 {
147 appIdReloadInProgress = true;
148 pthread_mutex_unlock(&appIdReloadMutex);
149 return;
150 }
151 pthread_mutex_unlock(&appIdReloadMutex);
152 nanosleep(&reloadPollTime, NULL);
153 }
154 }
155
156
157 static void reloadUnlock(void)
158 {
159 pthread_mutex_lock(&appIdReloadMutex);
160 appIdReloadInProgress = false;
161 pthread_mutex_unlock(&appIdReloadMutex);
162 }
163
164 STATIC bool AppIdReloadAdjust(bool idle, tSfPolicyId raPolicyId, void* userData)
165 {
166 return AppIdServiceStateReloadAdjust(idle, appidStaticConfig->memcap);
167 }
168
169 static int AppIdReloadReloadVerify(struct _SnortConfig *sc, void *swap_config)
170 {
171 initializeAppIDForDispatch(sc);
172 if (swap_config)
173 {
174 tAppidStaticConfig* newConfig = (tAppidStaticConfig*)swap_config;
175 if (newConfig->memcap != appidStaticConfig->memcap)
176 {
177 _dpd.logMsg("AppId: old memcap %lu, new memcap %lu\n", appidStaticConfig->memcap, newConfig->memcap);
178 _dpd.reloadAdjustRegister(sc, "AppID", 0, AppIdReloadAdjust, NULL, NULL);
179 }
180 }
181 return 0;
182 }
183
184 /**
185 * \brief Callback function that handles AppId reload
186 *
187 * This function gets called on Snort reload in a separate thread. It starts
188 * loading AppId configuration in new_config.
189 *
190 * @param sc
191 * @param args
192 * @param new_config return parameter to hold AppId configuration
193 * @return void
194 */
195 STATIC void AppIdReload(struct _SnortConfig *sc, char *args, void **new_config)
196 {
197 tSfPolicyId policy_id;
198
199 reloadWait();
200
201 policy_id = _dpd.getParserPolicy(sc);
202
203 if (policy_id == _dpd.getDefaultPolicy())
204 AppIdAddPortsToStream5Filter(sc, policy_id);
205
206 if (*new_config == NULL)
207 {
208 tAppidStaticConfig* newConfig;
209 if (NULL == (newConfig = (tAppidStaticConfig*)malloc(sizeof(*newConfig))))
210 {
211 _dpd.fatalMsg("AppID failed to allocate memory for new configuration\n");
212 }
213 appIdConfigParse(newConfig, args);
214 // Start loading AppId configuration into new_config
215 AppIdCommonReload(newConfig, (void**)&newConfig->newAppIdConfig);
216 *new_config = (void*)newConfig;
217 }
218 }
219
220 /**
221 * \brief Callback function that handles configuration swap on reload
222 *
223 * This function gets called after AppIdReload() returns. At this point,
224 * AppIdReload() is done with loading the configuration into swap_config
225 * and swap_config is ready to use.
226 *
227 * @param sc
228 * @param swap_config pointer to data structure containing new configuration.
229 * This data structure was populated by AppIdReload().
230 * @return pointer to old configuration
231 */
232 STATIC void *AppIdReloadSwap(struct _SnortConfig *sc, void *swap_config)
233 {
234 struct timeval startTime;
235 struct timeval endTime;
236 double elapsedTime;
237 tAppidStaticConfig* tmpConfig = NULL;
238
239 if (swap_config)
240 {
241 gettimeofday(&startTime, NULL);
242
243 tmpConfig = appidStaticConfig;
244 appidStaticConfig = (tAppidStaticConfig*)swap_config;
245
246 tmpConfig->newAppIdConfig = AppIdCommonReloadSwap(appidStaticConfig->newAppIdConfig);
247 appidStaticConfig->newAppIdConfig = NULL;
248 ThirdPartyAppIDReconfigure();
249
250 gettimeofday(&endTime, NULL);
251 elapsedTime = (endTime.tv_sec*1000.0) + (endTime.tv_usec/1000.0) - (startTime.tv_sec*1000.0) - (startTime.tv_usec/1000.0);
252
253 _dpd.logMsg("AppId reload swap time = %.3f msec\n", elapsedTime);
254 }
255
256 // Return old configuration data structure
257 return (void*)tmpConfig;
258 }
259
260 /**
261 * \brief Callback function that handles freeing of old configuration after
262 * configuration is swapped on a reload
263 *
264 * This function gets called after AppIdReloadSwap() is done. It frees the data
265 * structure that contains the old configuration.
266 *
267 * @param old_context pointer to old configuration
268 * @return void
269 */
270 STATIC void AppIdReloadFree(void *old_context)
271 {
272 AppIdStaticConfigFree((tAppidStaticConfig*)old_context);
273 reloadUnlock();
274 }
275
276 #endif // SNORT_RELOAD
277
278 /******** AppId Reconfigure Functions ********/
279
280 /**
281 * \brief Callback function that handles AppId reconfiguration
282 *
283 * This function gets called on AppId reconfiguration in a separate thread. It
284 * starts loading AppId configuration into new_context.
285 *
286 * @param type
287 * @param data
288 * @param length
289 * @param new_context return parameter to hold AppId configuration
290 * @param statusBuf
291 * @param statusBuf_Len
292 * @return 0 on success
293 */
294 STATIC int AppIdReconfigure(uint16_t type, const uint8_t *data, uint32_t length, void **new_context,
295 char* statusBuf, int statusBuf_len)
296 {
297 reloadWait();
298
299 if (*new_context == NULL)
300 {
301 AppIdCommonReload(appidStaticConfig, new_context);
302 }
303
304 return 0;
305 }
306
307 /**
308 * \brief Callback function that handles AppId reconfiguration swap
309 *
310 * This function gets called adter AppIdReconfigure() returns. At this point,
311 * AppIdReconfigure() is done with loading the configuration into new_context
312 * and new_context is ready to use.
313 *
314 * @param type
315 * @param new_context pointer to data structure that contains AppId's new
316 * configuration. This data structure was populated by AppIdReconfigure().
317 * @param old_context return parameter that points to old configuration
318 * @return 0 on success
319 */
320 STATIC int AppIdReconfigureSwap(uint16_t type, void *new_context, void **old_context)
321 {
322 struct timeval startTime;
323 struct timeval endTime;
324 double elapsedTime;
325
326 gettimeofday(&startTime, NULL);
327
328 if (new_context)
329 {
330 if (*old_context == NULL)
331 {
332 // Return current configuration in old_context
333 *old_context = AppIdCommonReloadSwap(new_context);
334 ThirdPartyAppIDReconfigure();
335 }
336 }
337
338 _dpd.logMsg("AppId", "Reconfigured");
339
340 gettimeofday(&endTime, NULL);
341 elapsedTime = (endTime.tv_sec*1000.0) + (endTime.tv_usec/1000.0) - (startTime.tv_sec*1000.0) - (startTime.tv_usec/1000.0);
342
343 _dpd.logMsg("AppId reconfigure swap time = %.3f msec\n", elapsedTime);
344
345 return 0;
346 }
347
348 /**
349 * \brief Callback function that handles freeing of old AppId configuration
350 *
351 * This function gets called after AppIdReconfigureSwap() returns. It frees the
352 * data strcuture that contains the old configuration.
353 *
354 * @param type
355 * @param old_context pointer to data structure that contains AppId's old
356 * configuration. This pointer was returned by AppIdReconfigureSwap().
357 * @param te
358 * @param f
359 * @return void
360 */
361 STATIC void AppIdReconfigureFree(uint16_t type, void *old_context, struct _THREAD_ELEMENT *te, ControlDataSendFunc f)
362 {
363 if (old_context)
364 {
365 AppIdCommonUnload(old_context);
366 }
367
368 reloadUnlock();
369 }
370
371 void AppIdDumpStats(int exit_flag)
372 {
373 _dpd.logMsg("Application Identification Preprocessor:\n");
374 _dpd.logMsg(" Total packets received : %lu\n", app_id_raw_packet_count);
375 _dpd.logMsg(" Total packets processed : %lu\n", app_id_processed_packet_count);
376 _dpd.logMsg(" Total packets ignored : %lu\n", app_id_ignored_packet_count);
377 _dpd.logMsg(" Total ongoing AppId sessions : %lu\n", app_id_ongoing_session);
378 _dpd.logMsg(" Total AppId sessions allocated : %lu\n", app_id_total_alloc);
379 _dpd.logMsg(" AppId session size : %lu\n", sizeof(tAppIdData));
380 if (exit_flag == 0) // Snort's SigDumpStatsHandler dumping stats intentionally
381 {
382 if (thirdparty_appid_module)
383 thirdparty_appid_module->print_stats();
384 AppIdServiceStateDumpStats();
385 RNAPndDumpLuaStats();
386 #ifdef SIDE_CHANNEL
387 AppIdPrintSSStats();
388 #endif
389 }
390 }
391
392 static void appIdIdleProcessing(void)
393 {
394 appIdStatsIdleFlush();
395 }
396
397 static void AppIdResetStats(int signal, void *data)
398 {
399 app_id_raw_packet_count = 0;
400 app_id_processed_packet_count = 0;
401 app_id_ignored_packet_count = 0;
402 app_id_ongoing_session = 0;
403 app_id_total_alloc = 0;
404 if (thirdparty_appid_module)
405 thirdparty_appid_module->reset_stats();
406 #ifdef SIDE_CHANNEL
407 AppIdResetSSStats();
408 #endif
409 }
410
411 static void AppIdCleanExit(int signal, void *unused)
412 {
413 AppIdCommonFini();
414 #ifdef SIDE_CHANNEL
415 AppIdCleanSS();
416 #endif
417 AppIdStaticConfigFree(appidStaticConfig);
418 }
419
420 static int ThirdPartyReload(uint16_t type, void *new_context, void **old_context)
421 {
422 if (thirdparty_appid_module != NULL)
423 {
424 thirdparty_appid_module->print_stats();
425 }
426 ThirdPartyAppIDFini();
427 ThirdPartyAppIDInit(appidStaticConfig);
428 return 0;
429 }
430
431 static void AppIdInit(struct _SnortConfig *sc, char *args)
432 {
433 static int once = 0;
434 tSfPolicyId policy_id = _dpd.getParserPolicy(sc);
435
436 if (!once)
437 {
438 _dpd.addPreprocExit(AppIdCleanExit, NULL, PRIORITY_LAST, PP_APP_ID);
439 # ifdef PERF_PROFILING
440 _dpd.addPreprocProfileFunc("fwApp", &appMatchPerfStats, 0, _dpd.totalPerfStats, NULL);
441 _dpd.addPreprocProfileFunc("fwAppTP", &tpPerfStats, 1, &appMatchPerfStats, NULL);
442 _dpd.addPreprocProfileFunc("fwLibAppTP", &tpLibPerfStats, 2, &tpPerfStats, NULL);
443 _dpd.addPreprocProfileFunc("fwHTTP", &httpPerfStats, 2, &tpPerfStats, NULL);
444 _dpd.addPreprocProfileFunc("fwClientPat", &clientMatchPerfStats, 1, &appMatchPerfStats, NULL);
445 _dpd.addPreprocProfileFunc("fwServicePat", &serviceMatchPerfStats, 1, &appMatchPerfStats, NULL);
446 _dpd.addPreprocProfileFunc("luaDetectors", &luaDetectorsPerfStats, 1, &appMatchPerfStats, NULL);
447 _dpd.addPreprocProfileFunc("cisco", &luaCiscoPerfStats, 2, &luaDetectorsPerfStats, NULL);
448 _dpd.addPreprocProfileFunc("custom", &luaCustomPerfStats, 2, &luaDetectorsPerfStats, NULL);
449 # endif
450 appid_preproc_status_bit = _dpd.sessionAPI->get_preprocessor_status_bit();
451
452 if (NULL == (appidStaticConfig = (tAppidStaticConfig*)malloc(sizeof(*appidStaticConfig))))
453 {
454 _dpd.fatalMsg("AppID failed to allocate memory for the configuration\n");
455 }
456 appIdConfigParse(appidStaticConfig, args);
457
458 AppIdCommonInit(appidStaticConfig);
459 ThirdPartyAppIDInit(appidStaticConfig);
460 if (appidStaticConfig->app_id_dump_ports)
461 {
462 dumpPorts(stdout, pAppidActiveConfig);
463 appInfoTableDump(pAppidActiveConfig);
464 exit(0);
465 }
466 _dpd.addPreprocResetStats(AppIdResetStats, NULL, PRIORITY_LAST, PP_APP_ID);
467 _dpd.registerPreprocStats(PREPROC_NAME, AppIdDumpStats);
468 /* Hook into control socket to handle reload */
469 _dpd.controlSocketRegisterHandler(73, AppIdReconfigure, AppIdReconfigureSwap, AppIdReconfigureFree);
470 _dpd.controlSocketRegisterHandler(74, AppIdDebug, NULL, NULL);
471 _dpd.controlSocketRegisterHandler(56, NULL, ThirdPartyReload, NULL);
472
473 _dpd.registerIdleHandler(appIdIdleProcessing);
474 _dpd.registerGetAppId(getOpenAppId);
475 if (!thirdparty_appid_module)
476 _dpd.streamAPI->register_http_header_callback(httpHeaderCallback);
477 _dpd.registerSslAppIdLookup(sslAppGroupIdLookup);
478 if (_dpd.streamAPI->service_event_subscribe(PP_SIP, SIP_EVENT_TYPE_SIP_DIALOG, SipSessionSnortCallback) == false)
479 DynamicPreprocessorFatalMessage("failed to subscribe to SIP_DIALOG\n");
480
481 if (_dpd.streamAPI->service_event_subscribe(PP_CIP, CIP_EVENT_TYPE_CIP_DATA, CipSessionSnortCallback) == false)
482 DynamicPreprocessorFatalMessage("failed to subscribe to CIP_EVENT_TYPE_CIP_DATA\n");
483
484 _dpd.registerSetTlsHostAppId(setTlsHost);
485
486 appIdApiInit(_dpd.appIdApi);
487 #ifdef SIDE_CHANNEL
488 _dpd.addFuncToPostConfigList(sc, AppIdSSPostConfigInit, NULL);
489 #endif
490 once = 1;
491 }
492
493 _dpd.addPreprocConfCheck(sc, AppIDCheckConfig);
494
495 if (policy_id == _dpd.getDefaultPolicy())
496 AppIdAddPortsToStream5Filter(sc, policy_id);
497 }
498
499 #define SetupApplicationPreproc DYNAMIC_PREPROC_SETUP
500
501 SF_SO_PUBLIC void SetupApplicationPreproc(void)
502 {
503 #ifndef SNORT_RELOAD
504 _dpd.registerPreproc(PREPROC_NAME, AppIdInit);
505 #else
506 _dpd.registerPreproc(PREPROC_NAME, AppIdInit, AppIdReload, AppIdReloadReloadVerify, AppIdReloadSwap, AppIdReloadFree);
507 #endif
508 }
509
510