"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/dynamic-preprocessors/appid/luaDetectorApi.c" (16 Oct 2020, 153087 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 "luaDetectorApi.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
22 /** @defgroup LuaDetectorBaseApi LuaDetectorBaseApi
23 * This module supports basic API towards Lua detectors.
24 *@{
25 */
26
27 #include <stdio.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32 #include <inttypes.h>
33 #include <assert.h>
34
35 #include "client_app_base.h"
36 #include "service_base.h"
37 #include "luaDetectorApi.h"
38 #include "luaDetectorModule.h"
39 #include "luaDetectorApi.h"
40 #include "luaDetectorFlowApi.h"
41 #include <pcre.h>
42 #include "httpCommon.h"
43 #include "sf_multi_mpse.h"
44 #include "fw_appid.h"
45 #include "http_url_patterns.h"
46 #include "service_ssl.h"
47 #include "hostPortAppCache.h"
48 #include "appInfoTable.h"
49 #include "ip_funcs.h"
50 #include "lengthAppCache.h"
51 #include "detector_dns.h"
52 #include "app_forecast.h"
53 #include "detector_pattern.h"
54 #include "detector_cip.h"
55
56 #define DETECTOR "Detector"
57 #define OVECCOUNT 30 /* should be a multiple of 3 */
58 #define URL_LIST_STEP_SIZE 5000
59
60 typedef enum {
61 LUA_LOG_CRITICAL = 0,
62 LUA_LOG_ERR = 1,
63 LUA_LOG_WARN = 2,
64 LUA_LOG_NOTICE = 3,
65 LUA_LOG_INFO = 4,
66 LUA_LOG_DEBUG = 5,
67 } LUA_LOG_LEVELS;
68
69 /*static const char * LuaLogLabel = "luaDetectorApi"; */
70 static ThrottleInfo error_throttleInfo = {0,30,0};
71
72 #ifdef PERF_PROFILING
73 PreprocStats luaDetectorsPerfStats;
74 PreprocStats luaCiscoPerfStats;
75 PreprocStats luaCustomPerfStats;
76 #endif
77
78 static void FreeDetectorAppUrlPattern(DetectorAppUrlPattern *pattern);
79
80 static DetectorUserData *toDetectorUserData (lua_State *L, int index)
81 {
82 DetectorUserData *bar = (DetectorUserData *)lua_touserdata(L, index);
83 if (bar == NULL) luaL_typerror(L, index, DETECTOR);
84 return bar;
85 }
86
87 DetectorUserData *checkDetectorUserData (
88 lua_State *L,
89 int index
90 )
91 {
92 DetectorUserData *bar;
93
94 luaL_checktype(L, index, LUA_TUSERDATA);
95
96 bar = (DetectorUserData *)luaL_checkudata(L, index, DETECTOR);
97 if (bar == NULL)
98 {
99 luaL_typerror(L, index, DETECTOR);
100 }
101
102 return bar;
103 }
104
105 static DetectorUserData *pushDetectorUserData(lua_State *L)
106 {
107 DetectorUserData *bar = (DetectorUserData *)lua_newuserdata(L, sizeof(DetectorUserData));
108
109 if (bar)
110 {
111 #ifdef LUA_DETECTOR_DEBUG
112 _dpd.debugMsg(DEBUG_LOG,"DetectorUserData %p: allocated\n\n",bar);
113 #endif
114 memset(bar, 0, sizeof(*bar));
115
116 if ((bar->pDetector = (Detector *)calloc(1, sizeof(Detector))) == NULL)
117 {
118 lua_pop(L, -1);
119
120 return NULL;
121 }
122
123 luaL_getmetatable(L, DETECTOR);
124 lua_setmetatable(L, -2);
125
126 #ifdef LUA_DETECTOR_DEBUG
127 _dpd.debugMsg(DEBUG_LOG,"Detector %p: allocated\n\n",bar->pDetector);
128 #endif
129 }
130 return bar;
131 }
132
133 Detector *createDetector(
134 lua_State *L,
135 const char *detectorName
136 )
137 {
138 DetectorUserData *pUserData;
139 Detector *detector;
140
141 pUserData = pushDetectorUserData(L);
142
143 if (!pUserData || !pUserData->pDetector)
144 {
145 _dpd.errMsg( "Failed to allocate memory.");
146 return NULL;
147 }
148
149 detector = pUserData->pDetector;
150
151 lua_pushvalue( L, -1 ); /*create a copy of userData */
152 detector->detectorUserDataRef = luaL_ref( L, LUA_REGISTRYINDEX );
153 detector->name = strdup(detectorName);
154 if (!detector->name)
155 {
156 free(pUserData->pDetector);
157 return NULL;
158 }
159
160 detector->myLuaState = L;
161 pthread_mutex_init(&detector->luaReloadMutex, NULL);
162
163 return detector;
164 }
165
166
167 /**must be called only when RNA is exitting.
168 */
169 void freeDetector(Detector *detector)
170 {
171 tDetectorPackageInfo *pkg = &detector->packageInfo;
172
173 if (!detector)
174 return;
175
176 if (detector->server.pServiceElement)
177 {
178 free(detector->server.pServiceElement);
179 }
180
181 if (detector->server.serviceModule.name)
182 {
183 free((void *)(detector->server.serviceModule.name));
184 }
185
186 if (pkg->name)
187 {
188 free(pkg->name);
189 }
190 if (pkg->client.initFunctionName)
191 {
192 free(pkg->client.initFunctionName);
193 }
194 if (pkg->client.cleanFunctionName)
195 {
196 free(pkg->client.cleanFunctionName);
197 }
198 if (pkg->client.validateFunctionName)
199 {
200 free(pkg->client.validateFunctionName);
201 }
202 if (pkg->server.initFunctionName)
203 {
204 free(pkg->server.initFunctionName);
205 }
206 if (pkg->server.cleanFunctionName)
207 {
208 free(pkg->server.cleanFunctionName);
209 }
210 if (pkg->server.validateFunctionName)
211 {
212 free(pkg->server.validateFunctionName);
213 }
214
215 /*The detectorUserData itself is a userdata and therefore be freed by Lua side. */
216 if (detector->detectorUserDataRef != LUA_REFNIL)
217 {
218 DetectorUserData *pUserData;
219
220 lua_rawgeti(detector->myLuaState, LUA_REGISTRYINDEX, detector->detectorUserDataRef);
221 pUserData = checkDetectorUserData(detector->myLuaState, -1);
222 if (pUserData)
223 {
224 pUserData->pDetector = NULL;
225 }
226
227 luaL_unref (detector->myLuaState, LUA_REGISTRYINDEX, detector->detectorUserDataRef);
228 detector->detectorUserDataRef = LUA_REFNIL;
229 }
230
231 if (detector->callbackFcnName)
232 {
233 free(detector->callbackFcnName);
234 }
235
236 free(detector->name);
237 free(detector->validatorBuffer);
238
239 #ifdef LUA_DETECTOR_DEBUG
240 _dpd.debugMsg(DEBUG_LOG,"Detector %p: freed\n\n",detector);
241 #endif
242 free(detector);
243 }
244
245 int detector_Callback(
246 const uint8_t *data,
247 uint16_t size,
248 const int dir,
249 tAppIdData *flowp,
250 const SFSnortPacket *pkt,
251 Detector *detector,
252 const tAppIdConfig *pConfig
253 )
254 {
255 int retValue;
256 lua_State *myLuaState;
257 char *callbackFn;
258 char *detectorName;
259 PROFILE_VARS;
260 #ifdef PERF_PROFILING
261 PreprocStats *pPerfStats1;
262 PreprocStats *pPerfStats2;
263 #endif
264
265 if (!data || !flowp || !pkt || !detector)
266 {
267 return -10;
268 }
269
270 #ifdef PERF_PROFILING
271 if (detector->isCustom)
272 pPerfStats1 = &luaCustomPerfStats;
273 else
274 pPerfStats1 = &luaCiscoPerfStats;
275 pPerfStats2 = detector->pPerfStats;
276 #endif
277 PREPROC_PROFILE_START(luaDetectorsPerfStats);
278 PREPROC_PROFILE_START((*pPerfStats1));
279 PREPROC_PROFILE_START((*pPerfStats2));
280
281 myLuaState = detector->myLuaState;
282 detector->validateParams.data = data;
283 detector->validateParams.size = size;
284 detector->validateParams.dir = dir;
285 detector->validateParams.flowp = flowp;
286 detector->validateParams.pkt = (SFSnortPacket *)pkt;
287 callbackFn = detector->callbackFcnName;
288 detectorName = detector->name;
289
290 /* Bail out if we cannot acquire the lock on the detector.
291 To avoid bailing out, use recursive mutex instead. */
292 if( pthread_mutex_trylock(&detector->luaReloadMutex))
293 {
294 detector->validateParams.pkt = NULL;
295 PREPROC_PROFILE_END((*pPerfStats2));
296 PREPROC_PROFILE_END((*pPerfStats1));
297 PREPROC_PROFILE_END(luaDetectorsPerfStats);
298 return -11;
299 }
300
301 if ((!callbackFn) || !(lua_checkstack(myLuaState, 1)))
302 {
303 _dpd.errMsgThrottled(&error_throttleInfo,
304 "Detector %s: invalid LUA %s\n",
305 detectorName, lua_tostring(myLuaState, -1));
306 detector->validateParams.pkt = NULL;
307 pthread_mutex_unlock(&detector->luaReloadMutex);
308 PREPROC_PROFILE_END((*pPerfStats2));
309 PREPROC_PROFILE_END((*pPerfStats1));
310 PREPROC_PROFILE_END(luaDetectorsPerfStats);
311 return -10;
312 }
313
314 lua_getglobal(myLuaState, callbackFn);
315
316 #ifdef LUA_DETECTOR_DEBUG
317 _dpd.debugMsg(DEBUG_LOG,"Detector %s: Lua Memory usage %d\n", detectorName, lua_gc(myLuaState, LUA_GCCOUNT,0));
318 _dpd.debugMsg(DEBUG_LOG,"Detector %s: validating\n", detectorName);
319 #endif
320 if (lua_pcall(myLuaState, 0, 1, 0 ))
321 {
322 _dpd.errMsg("Detector %s: Error validating %s\n", detectorName, lua_tostring(myLuaState, -1));
323 detector->validateParams.pkt = NULL;
324 pthread_mutex_unlock(&detector->luaReloadMutex);
325 PREPROC_PROFILE_END((*pPerfStats2));
326 PREPROC_PROFILE_END((*pPerfStats1));
327 PREPROC_PROFILE_END(luaDetectorsPerfStats);
328 return -10;
329 }
330
331 /**detectorFlows must be destroyed after each packet is processed.*/
332 sflist_static_free_all(&allocatedFlowList, freeDetectorFlow);
333
334 /* retrieve result */
335 if (!lua_isnumber(myLuaState, -1))
336 {
337 _dpd.errMsg("Detector %s: Validator returned non-numeric value\n", detectorName);
338 detector->validateParams.pkt = NULL;
339 pthread_mutex_unlock(&detector->luaReloadMutex);
340 PREPROC_PROFILE_END((*pPerfStats2));
341 PREPROC_PROFILE_END((*pPerfStats1));
342 PREPROC_PROFILE_END(luaDetectorsPerfStats);
343 retValue = -10;
344 }
345
346 retValue = lua_tonumber(myLuaState, -1);
347 lua_pop(myLuaState, 1); /* pop returned value */
348 /*lua_settop(myLuaState, 0); */
349
350 #ifdef LUA_DETECTOR_DEBUG
351 _dpd.debugMsg(DEBUG_LOG,"Detector %s: Validator returned %d\n", detectorName, retValue);
352 #endif
353
354 detector->validateParams.pkt = NULL;
355
356 pthread_mutex_unlock(&detector->luaReloadMutex);
357 PREPROC_PROFILE_END((*pPerfStats2));
358 PREPROC_PROFILE_END((*pPerfStats1));
359 PREPROC_PROFILE_END(luaDetectorsPerfStats);
360
361 return retValue;
362 }
363
364 static int Detector_registerClientCallback(lua_State *L)
365 {
366 tAppId appId;
367 const char *callback;
368 Detector *detector;
369 int index = 1;
370
371 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
372 appId = lua_tonumber(L, index++);
373 callback = lua_tostring(L, index++);
374
375 if (!detectorUserData || !callback)
376 {
377 lua_pushnumber(L, -1);
378 return 1; /*number of results */
379 }
380
381 detector = detectorUserData->pDetector;
382
383 if (!(detector->callbackFcnName = strdup(callback)))
384 {
385 lua_pushnumber(L, -1);
386 return 1;
387 }
388 appSetClientDetectorCallback(detector_Callback, appId, detector, detector->pAppidNewConfig);
389
390 lua_pushnumber(L, 0);
391 return 1;
392 }
393
394 static int Detector_registerServiceCallback(lua_State *L)
395 {
396 tAppId appId;
397 const char *callback;
398 Detector *detector;
399 int index = 1;
400
401 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
402 appId = lua_tonumber(L, index++);
403 callback = lua_tostring(L, index++);
404
405 if (!detectorUserData || !callback)
406 {
407 lua_pushnumber(L, -1);
408 return 1; /*number of results */
409 }
410
411 detector = detectorUserData->pDetector;
412
413 if (!(detector->callbackFcnName = strdup(callback)))
414 {
415 lua_pushnumber(L, -1);
416 return 1;
417 }
418 appSetServiceDetectorCallback(detector_Callback, appId, detector, detector->pAppidNewConfig);
419
420 lua_pushnumber(L, 0);
421 return 1;
422 }
423
424 /*converts Luastring to C compatible string. */
425 static int storeLuaString(const char *LuaString, char **CString)
426 {
427 char *string = *CString;
428
429 if (!LuaString)
430 {
431 return 0;
432 }
433
434 *CString = strdup(LuaString);
435 if (*CString == NULL)
436 {
437 *CString = string;
438 return -1;
439 }
440 if (string)
441 {
442 free(string);
443 }
444
445 return 0;
446 }
447
448 /*check service element, Allocate if necessary */
449 int checkServiceElement(
450 Detector *detector
451 )
452 {
453 if (!detector->server.pServiceElement)
454 {
455 detector->server.pServiceElement = calloc(1, sizeof(*detector->server.pServiceElement));
456 if (!detector->server.pServiceElement)
457 {
458 return 0;
459 }
460 detector->server.pServiceElement->name = detector->server.serviceModule.name;
461 }
462
463 return 1;
464 }
465
466 /**Creates a new detector instance. Creates a new detector instance and leaves the instance
467 * on stack. This is the first call by a lua detector to create and instance. Later calls
468 * provide the detector instance.
469 *
470 * @param Lua_State* - Lua state variable.
471 * @param serviceName/stack - name of service
472 * @param pValidator/stack - service validator function name
473 * @param pFini/stack - service clean exit function name
474 * @return int - Number of elements on stack, which should be 1 if success 0 otherwise.
475 * @return detector - a detector instance on stack if successful
476 */
477
478 static int service_init(lua_State *L)
479 {
480 const char *pValidator;
481 const char *pServiceName;
482 const char *pFini;
483 Detector *detector;
484
485 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
486 pServiceName = lua_tostring(L, 2);
487 pValidator = lua_tostring(L, 3);
488 pFini = lua_tostring(L, 4);
489
490 if ((!detectorUserData) || (!pServiceName) || (!pValidator) || (!pFini))
491 {
492 return 0;
493 }
494
495 detector = detectorUserData->pDetector;
496
497 lua_getglobal(L, pValidator);
498 lua_getglobal(L, pFini);
499 if (!(lua_isfunction(L, -1)) || !(lua_isfunction(L, -2)))
500 {
501 _dpd.errMsg("%s: attempted setting validator/fini to non-function\n",detector->server.serviceModule.name);
502 lua_pop(L, 2);
503 return 0;
504 }
505
506 lua_pop(L, 2);
507
508 /*old value is preserved so no error checks needed. */
509 if (!detector->server.serviceModule.name)
510 storeLuaString(pServiceName, (char **)&detector->server.serviceModule.name);
511 storeLuaString(pValidator, &detector->packageInfo.server.validateFunctionName);
512 storeLuaString(pFini, &detector->packageInfo.server.cleanFunctionName);
513
514 /*create a ServiceElement */
515 if (checkServiceElement(detector))
516 {
517 detector->server.pServiceElement->validate = validateAnyService;
518 detector->server.pServiceElement->userdata = detector;
519
520 detector->server.pServiceElement->detectorType = DETECTOR_TYPE_DECODER;
521 }
522
523 #ifdef LUA_DETECTOR_DEBUG
524 _dpd.debugMsg(DEBUG_LOG,"allocated detector = %p\n",detector);
525 #endif
526 return 1;
527 }
528
529 /**Register a pattern for fast pattern matching. Lua detector calls this function to register a pattern
530 * for fast pattern matching. This is similar to registerPattern in traditional C detector.
531 *
532 * @param Lua_State* - Lua state variable.
533 * @param detector/stack - detector object
534 * @param protocol/stack - protocol type. Values can be {tcp=6, udp=17 }
535 * @param pattern/stack - pattern string.
536 * @param size/stack - number of bytes in pattern
537 * @param position/stack - position offset where to start matching pattern.
538 * @return int - Number of elements on stack, which is always 1.
539 * @return status/stack - 0 if successful, -1 otherwise.
540 */
541 static int service_registerPattern(
542 lua_State *L
543 )
544 {
545 int protocol;
546 size_t size;
547 const char *pattern;
548 unsigned int position;
549 Detector *detector;
550 int index = 1;
551
552 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
553 protocol = lua_tonumber(L, index++);
554 pattern = lua_tostring(L, index++);
555 size = lua_tonumber(L, index++);
556 position = lua_tonumber(L, index++);
557
558 if ((pattern == NULL) || (detectorUserData == NULL))
559 {
560 lua_pushnumber(L, -1);
561 return 1; /*number of results */
562 }
563
564 detector = detectorUserData->pDetector;
565
566 /*Note: we can not give callback into lua directly so we have to */
567 /*give a local callback function, which will do demuxing and */
568 /*then call lua callback function. */
569
570 /*mpse library does not hold reference to pattern therefore we dont need to allocate it. */
571
572 ServiceRegisterPatternDetector(validateAnyService, protocol, (uint8_t *)pattern,
573 size, position, detector, detector->server.serviceModule.name);
574
575 lua_pushnumber(L, 0);
576 return 1; /*number of results */
577 }
578
579 static int common_registerAppId(
580 lua_State *L
581 )
582 {
583 unsigned int appId;
584 Detector *detector;
585 int index = 1;
586
587 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
588 appId = lua_tonumber(L, index++);
589
590 if (detectorUserData == NULL)
591 {
592 lua_pushnumber(L, -1);
593 return 1; /*number of results */
594 }
595
596 detector = detectorUserData->pDetector;
597
598 if (detector->packageInfo.server.initFunctionName)
599 appSetLuaServiceValidator(validateAnyService, appId, APPINFO_FLAG_SERVICE_ADDITIONAL, (void *)detector);
600 if (detector->packageInfo.client.initFunctionName)
601 appSetLuaClientValidator(validateAnyClientApp, appId, APPINFO_FLAG_CLIENT_ADDITIONAL, (void *)detector);
602
603 appInfoSetActive(appId, true);
604
605 lua_pushnumber(L, 0);
606 return 1; /*number of results */
607 }
608
609 static int Detector_htons(
610 lua_State *L
611 )
612 {
613 unsigned short aShort;
614 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
615 aShort = lua_tonumber(L, 2);
616
617 if (detectorUserData == NULL)
618 {
619 lua_pushnumber(L, -1);
620 return 1;
621 }
622
623 lua_pushnumber(L, htons(aShort));
624 return 1;
625 }
626
627 static int Detector_htonl(
628 lua_State *L
629 )
630 {
631 unsigned int anInt;
632
633 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
634 anInt = lua_tonumber(L, 2);
635
636 if (detectorUserData == NULL)
637 {
638 lua_pushnumber(L, -1);
639 return 1;
640 }
641
642 lua_pushnumber(L, htonl(anInt));
643 return 1;
644 }
645
646 /**Logs messages from detectors into wherever /etc/syslog.conf directs them.
647 * examples are:
648 * detector:log(DC.logLevel.warning, 'a warning')
649 *
650 *@param level - level of message. See DetectorCommon for enumeration.
651 *@param message - message to be logged.
652 */
653 static int Detector_logMessage(
654 lua_State *L
655 )
656 {
657 unsigned int level;
658 const char *message;
659 Detector *detector;
660 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
661
662 level = lua_tonumber(L, 2);
663 message = lua_tostring(L, 3);
664
665 if (detectorUserData == NULL)
666 {
667 return 0;
668 }
669
670 detector = detectorUserData->pDetector;
671
672 switch (level)
673 {
674 case LUA_LOG_CRITICAL:
675 _dpd.fatalMsg("%s:%s\n",detector->server.serviceModule.name, message);
676 break;
677 case LUA_LOG_ERR:
678 _dpd.errMsg("%s:%s\n",detector->server.serviceModule.name, message);
679 break;
680 case LUA_LOG_WARN:
681 _dpd.errMsg("%s:%s\n",detector->server.serviceModule.name, message);
682 break;
683 case LUA_LOG_NOTICE:
684 _dpd.logMsg("%s:%s\n",detector->server.serviceModule.name, message);
685 break;
686 case LUA_LOG_INFO:
687 _dpd.logMsg("%s:%s\n",detector->server.serviceModule.name, message);
688 break;
689 case LUA_LOG_DEBUG:
690 DEBUG_WRAP(DebugMessage(DEBUG_APPID, "%s:%s\n",detector->server.serviceModule.name, message););
691 break;
692 default:
693 break;
694 }
695
696 return 0;
697 }
698
699 /** Analyze application payload
700 *
701 * @param Lua_State* - Lua state variable.
702 * @param detector/stack - detector object
703 * @param major/stack - major number of application
704 * @param minor/stack - minor number of application
705 * @param flags/stack - any flags
706 * @return int - Number of elements on stack, which is always 0.
707 */
708 static int service_analyzePayload(
709 lua_State *L
710 )
711 {
712 unsigned int payloadId;
713 Detector *detector;
714 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
715
716 payloadId = lua_tonumber(L, 2);
717
718 /*check inputs and whether this function is called in context of a */
719 /*packet */
720 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
721 {
722 lua_pushnumber(L, -1);
723 return 1;
724 }
725
726 detector = detectorUserData->pDetector;
727
728 detector->validateParams.flowp->payloadAppId = payloadId;
729
730 lua_pushnumber(L, 0);
731 return 1;
732 }
733
734 /**Design notes: Due to following two design limitations:
735 * a. lua validate functions, known only at runtime, can not be wrapped inside unique
736 * C functions at runtime and
737 * b. core engine can not call lua functions directly.
738 *
739 * There must be a common validate function in C that in turn calls relevent Lua functions.
740 * Right now there is only one detector so there is a one-to-one mapping, but the framework
741 * will have to support multiple detectors in production environment. Core engine API will be
742 * changed to take an additional void* that will be used to call only a unique detector.
743 */
744 /*Common validate function that wraps lua based validate functions. */
745 int validateAnyService(ServiceValidationArgs *args)
746 {
747 int retValue;
748 lua_State *myLuaState = NULL;
749 const char *serverName;
750 struct _Detector *detector = args->userdata;
751 PROFILE_VARS;
752 #ifdef PERF_PROFILING
753 PreprocStats *pPerfStats1;
754 PreprocStats *pPerfStats2;
755 #endif
756
757 if (!detector)
758 {
759 _dpd.errMsg( "invalid LUA parameters");
760 return SERVICE_ENULL;
761 }
762
763 #ifdef PERF_PROFILING
764 if (detector->isCustom)
765 pPerfStats1 = &luaCustomPerfStats;
766 else
767 pPerfStats1 = &luaCiscoPerfStats;
768 pPerfStats2 = detector->pPerfStats;
769 #endif
770 PREPROC_PROFILE_START(luaDetectorsPerfStats);
771 PREPROC_PROFILE_START((*pPerfStats1));
772 PREPROC_PROFILE_START((*pPerfStats2));
773
774 myLuaState = detector->myLuaState;
775 detector->validateParams.data = args->data;
776 detector->validateParams.size = args->size;
777 detector->validateParams.dir = args->dir;
778 detector->validateParams.flowp = args->flowp;
779 detector->validateParams.pkt = args->pkt;
780 serverName = detector->name;
781
782 /*Note: Some frequently used header fields may be extracted and stored in detector for */
783 /*better performance. */
784
785 pthread_mutex_lock(&detector->luaReloadMutex);
786 if ((!detector->packageInfo.server.validateFunctionName) || !(lua_checkstack(myLuaState, 1)))
787 {
788 _dpd.errMsgThrottled(&error_throttleInfo,
789 "server %s: invalid LUA %s\n",
790 serverName, lua_tostring(myLuaState, -1));
791 detector->validateParams.pkt = NULL;
792 pthread_mutex_unlock(&detector->luaReloadMutex);
793 PREPROC_PROFILE_END((*pPerfStats2));
794 PREPROC_PROFILE_END((*pPerfStats1));
795 PREPROC_PROFILE_END((luaDetectorsPerfStats));
796 return SERVICE_ENULL;
797 }
798
799 lua_getglobal(myLuaState, detector->packageInfo.server.validateFunctionName);
800
801 #ifdef LUA_DETECTOR_DEBUG
802 _dpd.debugMsg(DEBUG_LOG,"server %s: Lua Memory usage %d\n",serverName, lua_gc(myLuaState, LUA_GCCOUNT,0));
803 _dpd.debugMsg(DEBUG_LOG,"server %s: validating\n",serverName);
804 #endif
805 if (lua_pcall(myLuaState, 0, 1, 0 ))
806 {
807 /*Runtime Lua errors are suppressed in production code since detectors are written for efficiency */
808 /*and with defensive minimum checks. Errors are dealt as exceptions that dont impact processing */
809 /*by other detectors or future packets by the same detector. */
810 _dpd.errMsg("server %s: error validating %s\n",serverName, lua_tostring(myLuaState, -1));
811 detector->validateParams.pkt = NULL;
812 pthread_mutex_unlock(&detector->luaReloadMutex);
813 PREPROC_PROFILE_END((*pPerfStats2));
814 PREPROC_PROFILE_END((*pPerfStats1));
815 PREPROC_PROFILE_END(luaDetectorsPerfStats);
816 return SERVICE_ENULL;
817 }
818
819 /**detectorFlows must be destroyed after each packet is processed.*/
820 sflist_static_free_all(&allocatedFlowList, freeDetectorFlow);
821
822 /* retrieve result */
823 if (!lua_isnumber(myLuaState, -1))
824 {
825 _dpd.errMsg("server %s: validator returned non-numeric value\n",serverName);
826 detector->validateParams.pkt = NULL;
827 pthread_mutex_unlock(&detector->luaReloadMutex);
828 PREPROC_PROFILE_END((*pPerfStats2));
829 PREPROC_PROFILE_END((*pPerfStats1));
830 PREPROC_PROFILE_END(luaDetectorsPerfStats);
831 return SERVICE_ENULL;
832 }
833
834 retValue = lua_tonumber(myLuaState, -1);
835 lua_pop(myLuaState, 1); /* pop returned value */
836 /*lua_settop(myLuaState, 0); */
837
838 #ifdef LUA_DETECTOR_DEBUG
839 _dpd.debugMsg(DEBUG_LOG,"server %s: Validator returned %d\n",serverName, retValue);
840 #endif
841
842 detector->validateParams.pkt = NULL;
843 pthread_mutex_unlock(&detector->luaReloadMutex);
844
845 PREPROC_PROFILE_END((*pPerfStats2));
846 PREPROC_PROFILE_END((*pPerfStats1));
847 PREPROC_PROFILE_END(luaDetectorsPerfStats);
848 return retValue;
849 }
850
851
852 /**design: dont store serviceId in detector structure since a single detector
853 * can get serviceId for multiple protocols. For example SIP which gets Id for RTP and
854 * SIP services.
855 */
856
857 /**Get service id from database, given service name. Lua detectors call this function at init time
858 * get get a service Id (an integer) from database.
859 *
860 * @param Lua_State* - Lua state variable.
861 * @param detector/stack - detector object
862 * @param serviceName/stack - Name of service
863 * @return int - Number of elements on stack, which is always 1.
864 * @return serviceId/stack - serviceId if successful, -1 otherwise.
865 */
866 static int service_getServiceId(
867 lua_State *L
868 )
869 {
870 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
871
872 if (detectorUserData == NULL)
873 {
874 lua_pushnumber(L, 0);
875 return 1;
876 }
877
878 lua_pushnumber(L, detectorUserData->pDetector->server.serviceId);
879 return 1;
880 }
881
882 /**
883 * Design Notes: In these APIs, three different AppID contexts - pAppidNewConfig, pAppidOldConfig
884 * and pAppidActiveConfig are used. pAppidNewConfig is used in APIs related to the loading of the
885 * detector such as service_addPorts(), client_registerPattern(), etc. A detector is loaded either
886 * during reload or at initialization. Use of pAppidNewConfig will cause the data structures related
887 * to the detector such as service ports, patterns, etc to be saved in the new AppID context.
888 *
889 * The new AppID context becomes active at the end of initialization or at reload swap.
890 * FinalizeLuaModules() is called at this time, which changes all the detectors' pAppidActiveConfig
891 * references to the new context. Also, pAppidOldConfig will be changed to point to the previous
892 * AppID context. In the packet processing APIs such as service_addService(), client_addUser(), etc.
893 * pAppidActiveConfig is used.
894 *
895 * In the cleanup APIs such as service_removePorts(), Detector_fini(), etc., data structures in the
896 * old AppID conext need to be freed. Therefore, pAppidOldConfig is used in these APIs.
897 */
898
899 /**Add port for a given service. Lua detectors call this function to register ports on which a
900 * given service is expected to run.
901 *
902 * @param Lua_State* - Lua state variable.
903 * @param detector/stack - detector object
904 * @param protocol/stack - protocol type. Values can be {tcp=6, udp=17 }
905 * @param port/stack - port number to register.
906 * @return int - Number of elements on stack, which is always 1.
907 * @return status/stack - 0 if successful, -1 otherwise.
908 */
909 static int service_addPorts(
910 lua_State *L
911 )
912 {
913 RNAServiceValidationPort pp;
914 Detector *detector;
915 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
916
917 pp.proto = lua_tonumber(L, 2);
918 pp.port = lua_tonumber(L, 3);
919 pp.reversed_validation = lua_tonumber(L, 5);
920 pp.validate = &validateAnyService;
921
922 if (!detectorUserData || ((pp.proto != IPPROTO_UDP) && (pp.proto != IPPROTO_TCP))
923 || !pp.port)
924 {
925 lua_pushnumber(L, -1);
926 return 1;
927 }
928
929 detector = detectorUserData->pDetector;
930
931 if (ServiceAddPort(&pp, &detector->server.serviceModule, (void*)detector, detector->pAppidNewConfig))
932 {
933 lua_pushnumber(L, -1);
934 return 1;
935 }
936
937 detector->server.pServiceElement->ref_count++;
938
939 lua_pushnumber(L, 0);
940 return 1;
941 }
942
943 /**Remove all ports for a given service. Lua detectors call this function to remove ports for this service
944 * when exiting. This function is not used currently by any detectors.
945 *
946 * @param Lua_State* - Lua state variable.
947 * @param detector/stack - detector object
948 * @return int - Number of elements on stack, which is always 1.
949 * @return status/stack - 0 if successful, -1 otherwise.
950 */
951 static int service_removePorts(
952 lua_State *L
953 )
954 {
955 /*RNAServiceValidationFCN validate */
956 /*from initAPI */
957 Detector *detector;
958 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
959
960 if (detectorUserData == NULL)
961 {
962 lua_pushnumber(L, -1);
963 return 1;
964 }
965
966 detector = detectorUserData->pDetector;
967
968 detectorRemoveAllPorts(detector, detector->pAppidOldConfig);
969
970 lua_pushnumber(L, 0);
971 return 1;
972 }
973
974 /**Shared function between Lua API and RNA core.
975 */
976 void detectorRemoveAllPorts (
977 Detector *detector,
978 tAppIdConfig *pConfig
979 )
980 {
981 ServiceRemovePorts(&validateAnyService, (void*)detector, pConfig);
982 }
983
984 /**Set service name. Lua detectors call this function to set service name. It is preferred to set service name
985 * when a detector is created. Afterwards there is rarely a need to change service name.
986 *
987 * @param Lua_State* - Lua state variable.
988 * @param detector/stack - detector object
989 * @param serviceName/stack - Name of service
990 * @return int - Number of elements on stack, which is always 1.
991 * @return status/stack - 0 if successful, -1 otherwise.
992 */
993 static int service_setServiceName(
994 lua_State *L
995 )
996 {
997 #if 0
998 Detector *detector;
999 char *serviceName;
1000 int retValue = -1;
1001 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1002
1003 serviceName = (char *)lua_tostring(L, 2);
1004
1005 if (!detectorUserData || !serviceName)
1006 {
1007 lua_pushnumber(L, -1);
1008 return 1;
1009 }
1010
1011 detector = detectorUserData->pDetector;
1012
1013 retValue = storeLuaString(serviceName, (char **)&detector->server.serviceModule.name);
1014
1015 lua_pushnumber(L, retValue);
1016 return 1;
1017 #else
1018 lua_pushnumber(L, 0);
1019 return 1;
1020 #endif
1021 }
1022
1023 /**Get service name. Lua detectors call this function to get service name. There is
1024 * rarely a need to change service name.
1025 *
1026 * @param Lua_State* - Lua state variable.
1027 * @param detector/stack - detector object
1028 * @return int - Number of elements on stack, which is always 1.
1029 * @return serviceName/stack - service name if successful, nil otherwise.
1030 */
1031 static int service_getServiceName(
1032 lua_State *L
1033 )
1034 {
1035 Detector *detector;
1036 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1037
1038 if (detectorUserData == NULL)
1039 {
1040 return 0;
1041 }
1042
1043 detector = detectorUserData->pDetector;
1044
1045 lua_pushstring(L, detector->server.serviceModule.name);
1046 return 1;
1047 }
1048
1049 /**Is this a customer defined detector. Lua detectors can call this function to verify if the detector
1050 * was created by Sourcefire or not.
1051 *
1052 * @param Lua_State* - Lua state variable.
1053 * @param detector/stack - detector object
1054 * @return int - Number of elements on stack, which is always 1.
1055 * @return integer/stack - -1 if failed, 0 if sourcefire created, 1 otherwise.
1056 */
1057 static int service_isCustomDetector(
1058 lua_State *L
1059 )
1060 {
1061 Detector *detector;
1062 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1063
1064 if (detectorUserData == NULL)
1065 {
1066 lua_pushnumber(L, -1);
1067 return 1;
1068 }
1069
1070 detector = detectorUserData->pDetector;
1071
1072 lua_pushnumber(L, detector->isCustom);
1073 return 1;
1074 }
1075
1076 /**Set service validator Lua function name. Lua detectors use this function to set a lua function name
1077 * as service validator function. It is preferred to set validatorname when a detector is created.
1078 * Afterwards there is rarely a need to change service name.
1079 *
1080 * @param Lua_State* - Lua state variable.
1081 * @param detector/stack - detector object
1082 * @param validatorName/stack - Name of service validator
1083 * @return int - Number of elements on stack, which is always 0.
1084 */
1085 static int service_setValidator(
1086 lua_State *L
1087 )
1088 {
1089 Detector *detector;
1090 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1091 const char *pValidator;
1092
1093 if (detectorUserData == NULL)
1094 {
1095 lua_pushnumber(L, -1);
1096 return 1;
1097 }
1098
1099 detector = detectorUserData->pDetector;
1100
1101 pValidator = lua_tostring(L, 2);
1102 lua_getglobal(L, pValidator);
1103 if (!lua_isfunction(L, -1))
1104 {
1105 _dpd.errMsg("%s: attempted setting validator to non-function\n",detector->server.serviceModule.name);
1106 lua_pop(L, 1);
1107 lua_pushnumber(L, -1);
1108 return 1;
1109 }
1110
1111 lua_pop(L, 1);
1112
1113 if (storeLuaString(pValidator, &detector->packageInfo.server.validateFunctionName) == -1)
1114 {
1115 _dpd.errMsg( "memory allocation failure");
1116 lua_pushnumber(L, -1);
1117 return 1;
1118 }
1119
1120 lua_pushnumber(L, 0);
1121 return 1;
1122 }
1123
1124 /** Add data (validator function name) to a flow. Detector use this function when confirming a flow
1125 * belongs to this service.
1126 *
1127 * @param Lua_State* - Lua state variable.
1128 * @param detector/stack - detector object
1129 * @param sourcePort/stack - Source port number.
1130 * @return int - Number of elements on stack, which is always 0.
1131 */
1132 static int service_addDataId(
1133 lua_State *L
1134 )
1135 {
1136 Detector *detector;
1137 uint16_t sport;
1138 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1139
1140 sport = lua_tonumber(L, 2);
1141
1142 /*check inputs and whether this function is called in context of a */
1143 /*packet */
1144 if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
1145 || !detectorUserData->pDetector->validateParams.pkt)
1146 {
1147 lua_pushnumber(L, -1);
1148 return 1;
1149 }
1150
1151 detector = detectorUserData->pDetector;
1152
1153 AppIdFlowdataAddId(detector->validateParams.flowp, sport, detector->server.pServiceElement);
1154
1155 lua_pushnumber(L, 0);
1156 return 1;
1157 }
1158
1159 /** Add service id to a flow. Positive identification by a detector.
1160 *
1161 * @param Lua_State* - Lua state variable.
1162 * @param detector/stack - detector object
1163 * @param serviceId/stack - id of service postively identified on this flow.
1164 * @param vendorName/stack - name of vendor of service. This is optional.
1165 * @param version/stack - version of service. This is optional.
1166 * @return int - Number of elements on stack, which is always 1.
1167 * @return int/stack - values from enum SERVICE_RETCODE
1168 */
1169 static int service_addService(
1170 lua_State *L
1171 )
1172 {
1173 char *vendor, *version;
1174 unsigned int serviceId, retValue = SERVICE_ENULL;
1175 Detector *detector;
1176 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1177
1178 serviceId = lua_tonumber(L, 2);
1179 vendor = (char *)luaL_optstring(L, 3, NULL);
1180 version = (char *)luaL_optstring(L, 4, NULL);
1181
1182 /*check inputs (vendor and version may be null) and whether this function is */
1183 /*called in context of a packet */
1184 if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
1185 || !detectorUserData->pDetector->validateParams.pkt)
1186 {
1187 lua_pushnumber(L, SERVICE_ENULL);
1188 return 1;
1189 }
1190
1191 detector = detectorUserData->pDetector;
1192
1193 /*Phase2 - discuss RNAServiceSubtype will be maintained on lua side therefore the last parameter on the following call is NULL. */
1194 /*Subtype is not displayed on DC at present. */
1195 retValue = AppIdServiceAddService(detector->validateParams.flowp, detector->validateParams.pkt,
1196 detector->validateParams.dir, detector->server.pServiceElement,
1197 appGetAppFromServiceId(serviceId, detector->pAppidActiveConfig), vendor, version, NULL, NULL);
1198
1199 lua_pushnumber(L, retValue);
1200 return 1;
1201 }
1202
1203 /**Function confirms the flow is not running this service.
1204 *
1205 * @param Lua_State* - Lua state variable.
1206 * @param detector/stack - detector object
1207 * @return int - Number of elements on stack, which is always 1.
1208 * @return int/stack - values from enum SERVICE_RETCODE
1209 */
1210 static int service_failService(
1211 lua_State *L
1212 )
1213 {
1214 unsigned int retValue = SERVICE_ENULL;
1215 Detector *detector;
1216 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1217
1218 /*check inputs (vendor and version may be null) and whether this function is */
1219 /*called in context of a packet */
1220 if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
1221 || !detectorUserData->pDetector->validateParams.pkt)
1222 {
1223 lua_pushnumber(L, SERVICE_ENULL);
1224 return 1;
1225 }
1226
1227 detector = detectorUserData->pDetector;
1228
1229 retValue = AppIdServiceFailService(detector->validateParams.flowp, detector->validateParams.pkt,
1230 detector->validateParams.dir, detector->server.pServiceElement, APPID_SESSION_DATA_NONE, detector->pAppidActiveConfig, NULL);
1231
1232 lua_pushnumber(L, retValue);
1233 return 1;
1234
1235 }
1236
1237 /**Detector use this function to indicate the flow may belong to this flow.
1238 *
1239 * @param Lua_State* - Lua state variable.
1240 * @param detector/stack - detector object
1241 * @return int - Number of elements on stack, which is always 1.
1242 * @return int/stack - values from enum SERVICE_RETCODE
1243 */
1244 static int service_inProcessService(
1245 lua_State *L
1246 )
1247 {
1248 unsigned int retValue = -1;
1249 Detector *detector;
1250 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1251
1252 /*check inputs (vendor and version may be null) and whether this function is */
1253 /*called in context of a packet */
1254 if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
1255 || !detectorUserData->pDetector->validateParams.pkt)
1256 {
1257 lua_pushnumber(L, SERVICE_ENULL);
1258 return 1;
1259 }
1260
1261 detector = detectorUserData->pDetector;
1262
1263 retValue = AppIdServiceInProcess(detector->validateParams.flowp, detector->validateParams.pkt,
1264 detector->validateParams.dir, detector->server.pServiceElement, NULL);
1265
1266 lua_pushnumber(L, retValue);
1267 return 1;
1268 }
1269
1270 /**Detector use this function to indicate error in service identification.
1271 *
1272 * @param Lua_State* - Lua state variable.
1273 * @param detector/stack - detector object
1274 * @return int - Number of elements on stack, which is always 1.
1275 * @return int/stack - values from enum SERVICE_RETCODE
1276 */
1277 static int service_inCompatibleData(
1278 lua_State *L
1279 )
1280 {
1281 unsigned int retValue = SERVICE_ENULL;
1282 Detector *detector;
1283 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1284
1285 /*check inputs (vendor and version may be null) and whether this function is */
1286 /*called in context of a packet */
1287 if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
1288 || !detectorUserData->pDetector->validateParams.pkt)
1289 {
1290 lua_pushnumber(L, SERVICE_ENULL);
1291 return 1;
1292 }
1293
1294 detector = detectorUserData->pDetector;
1295
1296 retValue = AppIdServiceIncompatibleData(detector->validateParams.flowp, detector->validateParams.pkt,
1297 detector->validateParams.dir, detector->server.pServiceElement,
1298 APPID_SESSION_DATA_NONE, detector->pAppidActiveConfig, NULL);
1299
1300 lua_pushnumber(L, retValue);
1301 return 1;
1302 }
1303
1304 /** Get size of current packet. It should be noted that due to restrictions on sharing pointers
1305 * between C and Lua, packet data is maintained on C side. Lua side can get specific fields, run
1306 * memcmp and pattern matching on packet data.
1307 *
1308 * @param Lua_State* - Lua state variable.
1309 * @param detector/stack - detector object
1310 * @return int - Number of elements on stack, which is always 1 if successful, 0 otherwise.
1311 * @return packetSize/stack - size of packet on stack, if successful.
1312 */
1313 static int Detector_getPacketSize(
1314 lua_State *L
1315 )
1316 {
1317 Detector *detector;
1318 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1319
1320 if (detectorUserData == NULL)
1321 {
1322 return 0;
1323 }
1324
1325 detector = detectorUserData->pDetector;
1326
1327 lua_pushnumber(L, detector->validateParams.size);
1328 return 1;
1329 }
1330
1331 /**Get packet direction. A flow/session maintains initiater and responder sides. A packet direction
1332 * is determined wrt to the original initiater.
1333 *
1334 * @param Lua_State* - Lua state variable.
1335 * @param detector/stack - detector object
1336 * @return int - Number of elements on stack, which is always 1 if successful, 0 otherwise.
1337 * @return packetDir/stack - direction of packet on stack, if successful.
1338 */
1339 static int Detector_getPacketDir(
1340 lua_State *L
1341 )
1342 {
1343 Detector *detector;
1344 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1345
1346 if (detectorUserData == NULL)
1347 {
1348 /*can not return 0 in case of error, since 0 can be a valid value. */
1349 return 0;
1350 }
1351
1352 detector = detectorUserData->pDetector;
1353
1354 lua_pushnumber(L, detector->validateParams.dir);
1355 return 1;
1356 }
1357
1358 /**Perform a pcre match with grouping. A simple regular expression match with no grouping
1359 * can also be performed.
1360 *
1361 * @param Lua_State* - Lua state variable.
1362 * @param detector/stack - detector object
1363 * @return int - Number of group matches. May be 0 or more.
1364 * @return matchedStrings/stack - matched strings are pushed on stack starting with group 0.
1365 * There may be 0 or more strings.
1366 */
1367 static int Detector_getPcreGroups(
1368 lua_State *L
1369 )
1370 {
1371 Detector *detector;
1372 char *pattern;
1373 unsigned int offset;
1374 pcre *re;
1375 int ovector[OVECCOUNT];
1376 const char *error;
1377 int erroffset;
1378 int rc, i;
1379 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1380
1381 pattern = (char *)lua_tostring(L, 2);
1382 offset = lua_tonumber(L, 3); /*offset can be zero, no check necessary. */
1383
1384 if ((pattern == NULL) || (detectorUserData == NULL))
1385 {
1386 return 0;
1387 }
1388
1389 detector = detectorUserData->pDetector;
1390
1391 {
1392 /*compile the regular expression pattern, and handle errors */
1393 re = pcre_compile(
1394 pattern, /*the pattern */
1395 PCRE_DOTALL, /*default options - dot matches everything including newline */
1396 &error, /*for error message */
1397 &erroffset, /*for error offset */
1398 NULL); /*use default character tables */
1399
1400 if (re == NULL)
1401 {
1402 _dpd.errMsg("PCRE compilation failed at offset %d: %s\n",erroffset, error);
1403 return 0;
1404 }
1405
1406
1407 /*pattern match against the subject string. */
1408 rc = pcre_exec(
1409 re, /*compiled pattern */
1410 NULL, /*no extra data */
1411 (char *)detector->validateParams.data, /*subject string */
1412 detector->validateParams.size, /*length of the subject */
1413 offset, /*offset 0 */
1414 0, /*default options */
1415 ovector, /*output vector for substring information */
1416 OVECCOUNT); /*number of elements in the output vector */
1417
1418
1419 if (rc < 0)
1420 {
1421 /*Matching failed: clubbing PCRE_ERROR_NOMATCH with other errors. */
1422 pcre_free(re);
1423 return 0;
1424 }
1425
1426 /*Match succeded */
1427
1428 /*printf("\nMatch succeeded at offset %d", ovector[0]); */
1429 pcre_free(re);
1430
1431
1432 if (rc == 0)
1433 {
1434 /*overflow of matches */
1435 rc = OVECCOUNT/3;
1436 /*printf("ovector only has room for %d captured substrings", rc - 1); */
1437 _dpd.errMsg("ovector only has room for %d captured substrings\n",rc - 1);
1438 }
1439 }
1440
1441
1442
1443 lua_checkstack (L, rc);
1444 for (i = 0; i < rc; i++)
1445 {
1446 /*printf("%2d: %.*s\n", i, , substring_start); */
1447 lua_pushlstring(L, (char *)detector->validateParams.data + ovector[2*i], ovector[2*i+1] - ovector[2*i]);
1448 }
1449
1450 return rc;
1451 }
1452
1453 /**Performs a simple memory comparison.
1454 *
1455 * @param Lua_State* - Lua state variable.
1456 * @param detector/stack - detector object
1457 * @param pattern/stack - pattern to be matched.
1458 * @param patternLenght/stack - length of pattern
1459 * @param offset/stack - offset into packet payload where matching should start.
1460 *
1461 * @return int - Number of group matches. May be 1 if successful, and 0 if error is encountered.
1462 * @return memCmpResult/stack - returns -1,0,1 based on memcmp result.
1463 */
1464 static int Detector_memcmp(
1465 lua_State *L
1466 )
1467 {
1468 Detector *detector;
1469 char *pattern;
1470 unsigned int patternLen;
1471 unsigned int offset;
1472 int rc;
1473 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1474
1475 pattern = (char *)lua_tostring(L, 2);
1476 patternLen = lua_tonumber(L, 3);
1477 offset = lua_tonumber(L, 4); /*offset can be zero, no check necessary. */
1478
1479 if ((detectorUserData == NULL) || (pattern == NULL))
1480 {
1481 return 0;
1482 }
1483
1484 detector = detectorUserData->pDetector;
1485
1486 rc = memcmp((char *)detector->validateParams.data + offset, pattern, patternLen);
1487
1488 lua_checkstack (L, 1);
1489 lua_pushnumber(L, rc);
1490 return 1;
1491 }
1492
1493 /**Get Packet Protocol Type
1494 *
1495 * @param Lua_State* - Lua state variable.
1496 * @return int - Number of elements on stack, which is protocol type if successful, 0 otherwise.
1497 * @return protocol type TCP or UDP
1498 */
1499 static int Detector_getProtocolType (
1500 lua_State *L
1501 )
1502 {
1503 Detector *detector;
1504 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1505
1506 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt || !IPH_IS_VALID(detectorUserData->pDetector->validateParams.pkt))
1507 {
1508 lua_checkstack (L, 1);
1509 lua_pushnumber(L, 0);
1510 return 1;
1511 }
1512
1513 detector = detectorUserData->pDetector;
1514
1515 lua_checkstack (L, 1);
1516 lua_pushnumber(L, GET_IPH_PROTO(detector->validateParams.pkt));
1517 return 1;
1518 }
1519
1520 /**Get source IP address from IP header.
1521 *
1522 * @param Lua_State* - Lua state variable.
1523 * @param detector/stack - detector object
1524 * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
1525 * @return IPv4/stack - Source IPv4 addresss.
1526 */
1527 static int Detector_getPktSrcIPAddr(
1528 lua_State *L
1529 )
1530 {
1531 Detector *detector;
1532 sfaddr_t *ipAddr;
1533 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1534
1535 if (detectorUserData == NULL)
1536 {
1537 return 0;
1538 }
1539
1540 detector = detectorUserData->pDetector;
1541
1542 ipAddr = GET_SRC_IP(detector->validateParams.pkt);
1543
1544 lua_checkstack (L, 1);
1545 lua_pushnumber(L, sfaddr_get_ip4_value(ipAddr));
1546 return 1;
1547 }
1548
1549 /**Get source port number from IP header.
1550 *
1551 * @param Lua_State* - Lua state variable.
1552 * @param detector/stack - detector object
1553 * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
1554 * @return portNumber/stack - source port number.
1555 */
1556 static int Detector_getPktSrcPort(
1557 lua_State *L
1558 )
1559 {
1560 Detector *detector;
1561 unsigned int port;
1562 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1563
1564 if (detectorUserData == NULL)
1565 {
1566 return 0;
1567 }
1568
1569 detector = detectorUserData->pDetector;
1570
1571 port = detector->validateParams.pkt->src_port;
1572
1573 lua_checkstack (L, 1);
1574 lua_pushnumber(L, port);
1575 return 1;
1576 }
1577
1578 /**Get destination port number from IP header.
1579 *
1580 * @param Lua_State* - Lua state variable.
1581 * @param detector/stack - detector object
1582 * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
1583 * @return portNumber/stack - destination Port number.
1584 */
1585 static int Detector_getPktDstPort(
1586 lua_State *L
1587 )
1588 {
1589 Detector *detector;
1590 unsigned int port;
1591 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1592
1593 if (detectorUserData == NULL)
1594 {
1595 return 0;
1596 }
1597
1598 detector = detectorUserData->pDetector;
1599
1600 port = detector->validateParams.pkt->dst_port;
1601
1602 lua_checkstack (L, 1);
1603 lua_pushnumber(L, port);
1604 return 1;
1605 }
1606
1607 /**Get destination IP address from IP header.
1608 *
1609 * @param Lua_State* - Lua state variable.
1610 * @param detector/stack - detector object
1611 * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
1612 * @return IPv4/stack - destination IPv4 addresss.
1613 */
1614 static int Detector_getPktDstIPAddr(
1615 lua_State *L
1616 )
1617 {
1618 Detector *detector;
1619 sfaddr_t *ipAddr;
1620 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1621
1622 if (detectorUserData == NULL)
1623 {
1624 return 0;
1625 }
1626
1627 detector = detectorUserData->pDetector;
1628
1629 ipAddr = GET_DST_IP(detector->validateParams.pkt);
1630
1631 lua_checkstack (L, 1);
1632 lua_pushnumber(L, sfaddr_get_ip4_value(ipAddr));
1633 return 1;
1634 }
1635
1636
1637 /**Get packet count. This is used mostly for printing packet sequence
1638 * number when RNA is being tested with a pcap file.
1639 *
1640 * @param Lua_State* - Lua state variable.
1641 * @param detector/stack - detector object
1642 * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
1643 * @return packetCount/stack - Total packet processed by RNA.
1644 */
1645 static int Detector_getPktCount(
1646 lua_State *L
1647 )
1648 {
1649 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1650
1651 if (detectorUserData == NULL)
1652 {
1653 return 0;
1654 }
1655
1656 lua_checkstack (L, 1);
1657 lua_pushnumber(L, app_id_processed_packet_count);
1658 return 1;
1659 }
1660
1661 int validateAnyClientApp(
1662 const uint8_t *data,
1663 uint16_t size,
1664 const int dir,
1665 tAppIdData *flowp,
1666 SFSnortPacket *pkt,
1667 Detector *detector,
1668 const tAppIdConfig *pConfig
1669 )
1670 {
1671 int retValue;
1672 lua_State *myLuaState;
1673 char *validateFn;
1674 char *clientName;
1675 PROFILE_VARS;
1676 #ifdef PERF_PROFILING
1677 PreprocStats *pPerfStats1;
1678 PreprocStats *pPerfStats2;
1679 #endif
1680
1681 if (!data || !flowp || !pkt || !detector)
1682 {
1683 return CLIENT_APP_ENULL;
1684 }
1685
1686 #ifdef PERF_PROFILING
1687 if (detector->isCustom)
1688 pPerfStats1 = &luaCustomPerfStats;
1689 else
1690 pPerfStats1 = &luaCiscoPerfStats;
1691 pPerfStats2 = detector->pPerfStats;
1692 #endif
1693 PREPROC_PROFILE_START(luaDetectorsPerfStats);
1694 PREPROC_PROFILE_START((*pPerfStats1));
1695 PREPROC_PROFILE_START((*pPerfStats2));
1696
1697 myLuaState = detector->myLuaState;
1698 detector->validateParams.data = data;
1699 detector->validateParams.size = size;
1700 detector->validateParams.dir = dir;
1701 detector->validateParams.flowp = flowp;
1702 detector->validateParams.pkt = (SFSnortPacket *)pkt;
1703 validateFn = detector->packageInfo.client.validateFunctionName;
1704 clientName = detector->name;
1705
1706 pthread_mutex_lock(&detector->luaReloadMutex);
1707 if ((!validateFn) || !(lua_checkstack(myLuaState, 1)))
1708 {
1709 _dpd.errMsgThrottled(&error_throttleInfo,
1710 "client %s: invalid LUA %s\n",
1711 clientName, lua_tostring(myLuaState, -1));
1712 detector->validateParams.pkt = NULL;
1713 pthread_mutex_unlock(&detector->luaReloadMutex);
1714 PREPROC_PROFILE_END((*pPerfStats2));
1715 PREPROC_PROFILE_END((*pPerfStats1));
1716 PREPROC_PROFILE_END(luaDetectorsPerfStats);
1717 return CLIENT_APP_ENULL;
1718 }
1719
1720 lua_getglobal(myLuaState, validateFn);
1721
1722 #ifdef LUA_DETECTOR_DEBUG
1723 _dpd.debugMsg(DEBUG_LOG,"client %s: Lua Memory usage %d\n",clientName, lua_gc(myLuaState, LUA_GCCOUNT,0));
1724 _dpd.debugMsg(DEBUG_LOG,"client %s: validating\n",clientName);
1725 #endif
1726 if (lua_pcall(myLuaState, 0, 1, 0 ))
1727 {
1728 _dpd.errMsg("client %s: error validating %s\n",clientName, lua_tostring(myLuaState, -1));
1729 detector->validateParams.pkt = NULL;
1730 pthread_mutex_unlock(&detector->luaReloadMutex);
1731 PREPROC_PROFILE_END((*pPerfStats2));
1732 PREPROC_PROFILE_END((*pPerfStats1));
1733 PREPROC_PROFILE_END(luaDetectorsPerfStats);
1734 return SERVICE_ENULL;
1735 }
1736
1737 /**detectorFlows must be destroyed after each packet is processed.*/
1738 sflist_static_free_all(&allocatedFlowList, freeDetectorFlow);
1739
1740 /* retrieve result */
1741 if (!lua_isnumber(myLuaState, -1))
1742 {
1743 _dpd.errMsg("client %s: validator returned non-numeric value\n",clientName);
1744 detector->validateParams.pkt = NULL;
1745 pthread_mutex_unlock(&detector->luaReloadMutex);
1746 PREPROC_PROFILE_END((*pPerfStats2));
1747 PREPROC_PROFILE_END((*pPerfStats1));
1748 PREPROC_PROFILE_END(luaDetectorsPerfStats);
1749 retValue = SERVICE_ENULL;
1750 }
1751
1752 retValue = lua_tonumber(myLuaState, -1);
1753 lua_pop(myLuaState, 1); /* pop returned value */
1754 /*lua_settop(myLuaState, 0); */
1755
1756 #ifdef LUA_DETECTOR_DEBUG
1757 _dpd.debugMsg(DEBUG_LOG,"client %s: Validator returned %d\n",clientName, retValue);
1758 #endif
1759
1760 detector->validateParams.pkt = NULL;
1761 pthread_mutex_unlock(&detector->luaReloadMutex);
1762
1763 PREPROC_PROFILE_END((*pPerfStats2));
1764 PREPROC_PROFILE_END((*pPerfStats1));
1765 PREPROC_PROFILE_END(luaDetectorsPerfStats);
1766 return retValue;
1767 }
1768
1769 static int client_registerPattern(lua_State *L)
1770 {
1771 int protocol;
1772 size_t size;
1773 const char *pattern;
1774 unsigned int position;
1775 Detector *detector;
1776 int index = 1;
1777
1778 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
1779 protocol = lua_tonumber(L, index++);
1780 pattern = lua_tostring(L, index++);
1781 size = lua_tonumber(L, index++);
1782 position = lua_tonumber(L, index++);
1783
1784 if ((pattern == NULL) || (detectorUserData == NULL))
1785 {
1786 lua_pushnumber(L, -1);
1787 return 1; /*number of results */
1788 }
1789
1790 detector = detectorUserData->pDetector;
1791
1792 /*Note: we can not give callback into lua directly so we have to */
1793 /*give a local callback function, which will do demuxing and */
1794 /*then call lua callback function. */
1795
1796 /*mpse library does not hold reference to pattern therefore we dont need to allocate it. */
1797
1798 detector->client.appModule.userData = detector;
1799 clientAppLoadForConfigCallback((void *) &(detector->client.appModule), &detector->pAppidNewConfig->clientAppConfig);
1800 ClientAppRegisterPattern(validateAnyClientApp, protocol, (uint8_t*)pattern, size, position, 0, (void *)detector, &detector->pAppidNewConfig->clientAppConfig);
1801
1802 lua_pushnumber(L, 0);
1803 return 1; /*number of results */
1804 }
1805
1806 /**Creates a new detector instance. Creates a new detector instance and leaves the instance
1807 * on stack. This is the first call by a lua detector to create and instance. Later calls
1808 * provide the detector instance.
1809 *
1810 * @param Lua_State* - Lua state variable.
1811 * @param serviceName/stack - name of service
1812 * @param pValidator/stack - service validator function name
1813 * @param pFini/stack - service clean exit function name
1814 * @return int - Number of elements on stack, which should be 1 if success 0 otherwise.
1815 * @return detector - a detector instance on stack if successful
1816 */
1817
1818 static int client_init (lua_State *L)
1819 {
1820 /*nothing to do */
1821 return 0;
1822 }
1823
1824 static int service_addClient (lua_State *L)
1825 {
1826 tAppId clientAppId, serviceId;
1827 const char *version;
1828 Detector *detector;
1829 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1830
1831 clientAppId = lua_tonumber(L, 2);
1832 serviceId = lua_tonumber(L, 3);
1833 version = lua_tostring(L, 4);
1834
1835 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt
1836 || !version)
1837 {
1838 lua_pushnumber(L, -1);
1839 return 1;
1840 }
1841
1842 detector = detectorUserData->pDetector;
1843
1844 AppIdAddClientApp(detector->validateParams.pkt, detector->validateParams.dir, detector->pAppidActiveConfig, detector->validateParams.flowp, serviceId, clientAppId, version);
1845
1846 lua_pushnumber(L, 0);
1847 return 1;
1848 }
1849
1850 static int client_addApp(
1851 lua_State *L
1852 )
1853 {
1854 unsigned int serviceId, productId;
1855 const char *version;
1856 Detector *detector;
1857 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1858
1859 serviceId = lua_tonumber(L, 2);
1860 productId = lua_tonumber(L, 4);
1861 version = lua_tostring(L, 5);
1862
1863 /*check inputs and whether this function is called in context of a */
1864 /*packet */
1865 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt
1866 || !version)
1867 {
1868 lua_pushnumber(L, -1);
1869 return 1;
1870 }
1871
1872 detector = detectorUserData->pDetector;
1873
1874 if (!detector->client.appModule.api)
1875 {
1876 lua_pushnumber(L, -1);
1877 return 1;
1878 }
1879
1880 detector->client.appModule.api->add_app(detector->validateParams.pkt, (APPID_SESSION_DIRECTION) detector->validateParams.dir, detector->pAppidActiveConfig,
1881 detector->validateParams.flowp, appGetAppFromServiceId(serviceId, detector->pAppidActiveConfig), appGetAppFromClientId(productId, detector->pAppidActiveConfig), version);
1882
1883 lua_pushnumber(L, 0);
1884 return 1;
1885 }
1886
1887 static int client_addInfo(
1888 lua_State *L
1889 )
1890 {
1891 const char *info;
1892 Detector *detector;
1893 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1894
1895 info = lua_tostring(L, 2);
1896
1897 /*check inputs and whether this function is called in context of a */
1898 /*packet */
1899 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt
1900 || !info)
1901 {
1902 lua_pushnumber(L, -1);
1903 return 1;
1904 }
1905
1906 detector = detectorUserData->pDetector;
1907
1908 if (!detector->client.appModule.api)
1909 {
1910 lua_pushnumber(L, -1);
1911 return 1;
1912 }
1913
1914 detector->client.appModule.api->add_info(detector->validateParams.flowp, info);
1915
1916 lua_pushnumber(L, 0);
1917 return 1;
1918 }
1919
1920 static int client_addUser(
1921 lua_State *L
1922 )
1923 {
1924 unsigned int serviceId;
1925 const char *userName;
1926 Detector *detector;
1927 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1928
1929 userName = lua_tostring(L, 2);
1930 serviceId = lua_tonumber(L, 3);
1931
1932 /*check inputs and whether this function is called in context of a */
1933 /*packet */
1934 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt || !userName)
1935 {
1936 lua_pushnumber(L, -1);
1937 return 1;
1938 }
1939
1940 detector = detectorUserData->pDetector;
1941
1942 if (!detector->client.appModule.api)
1943 {
1944 lua_pushnumber(L, -1);
1945 return 1;
1946 }
1947
1948 detector->client.appModule.api->add_user(detector->validateParams.flowp, userName, appGetAppFromServiceId(serviceId, detector->pAppidActiveConfig), 1);
1949
1950 lua_pushnumber(L, 0);
1951 return 1;
1952 }
1953
1954 static int client_addPayload(
1955 lua_State *L
1956 )
1957 {
1958 unsigned int payloadId;
1959 Detector *detector;
1960 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
1961
1962 payloadId = lua_tonumber(L, 2);
1963
1964 /*check inputs and whether this function is called in context of a */
1965 /*packet */
1966 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
1967 {
1968 lua_pushnumber(L, -1);
1969 return 1;
1970 }
1971
1972 detector = detectorUserData->pDetector;
1973
1974 if (!detector->client.appModule.api)
1975 {
1976 lua_pushnumber(L, -1);
1977 return 1;
1978 }
1979
1980 detector->client.appModule.api->add_payload(detector->validateParams.flowp, appGetAppFromPayloadId(payloadId, detector->pAppidActiveConfig));
1981
1982 lua_pushnumber(L, 0);
1983 return 1;
1984 }
1985
1986 /**Get flow object from a detector object. The flow object is then used with flowApi.
1987 * A new copy of flow object is provided with every call. This can be optimized by maintaining
1988 * a single copy.
1989 *
1990 * @param Lua_State* - Lua state variable.
1991 * @param detector/stack - detector object
1992 * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
1993 * @return packetCount/stack - Total packet processed by RNA.
1994 * @todo maintain a single copy and return the same copy with every call to Detector_getFlow().
1995 */
1996 static int Detector_getFlow(
1997 lua_State *L
1998 )
1999 {
2000 DetectorFlowUserData *detectorFlowUserData;
2001 Detector *detector;
2002 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
2003
2004 /*check inputs and whether this function is called in context of a packet */
2005 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
2006 {
2007 return 0;
2008 }
2009
2010 detector = detectorUserData->pDetector;
2011
2012 detectorFlowUserData = pushDetectorFlowUserData(L);
2013 if (!detectorFlowUserData || !detectorFlowUserData->pDetectorFlow)
2014 {
2015 _dpd.errMsg( "Failed to allocate memory.");
2016 return 0;
2017 }
2018
2019 detectorFlowUserData->pDetectorFlow->pFlow = detector->validateParams.flowp;
2020
2021 #ifdef LUA_DETECTOR_DEBUG
2022 _dpd.debugMsg(DEBUG_LOG, "service %s, Detector_getFlow(): allocated DetectorFlow = %p",
2023 detector->server.serviceModule.name, detectorFlowUserData);
2024 #endif
2025 return 1;
2026 }
2027
2028 int Detector_addHttpPattern(lua_State *L)
2029 {
2030 int index = 1;
2031
2032 /* Verify detector user data and that we are not in packet context */
2033 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
2034 if (!detectorUserData)
2035 {
2036 _dpd.errMsg( "Invalid HTTP detector user data addHttpPattern.");
2037 return 0;
2038 }
2039
2040 /* Verify valid pattern type */
2041 enum httpPatternType pType = (enum httpPatternType) lua_tointeger(L, index++);
2042 if(pType < HTTP_PAYLOAD || pType > HTTP_URL)
2043 {
2044 _dpd.errMsg( "Invalid HTTP pattern type.");
2045 return 0;
2046 }
2047
2048 /* Verify valid DHSequence */
2049 DHPSequence seq = (DHPSequence) lua_tointeger(L, index++);
2050 if(seq < SINGLE || seq > USER_AGENT_HEADER)
2051 {
2052 _dpd.errMsg( "Invalid HTTP DHP Sequence.");
2053 return 0;
2054 }
2055
2056 uint32_t service_id = lua_tointeger(L, index++);
2057 uint32_t client_app = lua_tointeger(L, index++);
2058 /*uint32_t client_app_type =*/ lua_tointeger(L, index++);
2059 uint32_t payload = lua_tointeger(L, index++);
2060 /*uint32_t payload_type =*/ lua_tointeger(L, index++);
2061
2062 if (detectorUserData->pDetector->validateParams.pkt)
2063 {
2064 _dpd.errMsg("Invalid detector context addHttpPattern: service_id %u; client_app %u; payload %u\n",service_id, client_app, payload);
2065 return 0;
2066 }
2067
2068 /* Verify that pattern is a valid string */
2069 size_t pattern_size = 0;
2070 uint8_t* pattern_str = (uint8_t*) strdup(lua_tolstring(L, index++, &pattern_size));
2071 if(pattern_str == NULL || pattern_size == 0)
2072 {
2073 _dpd.errMsg( "Invalid HTTP pattern string.");
2074 free(pattern_str);
2075 return 0;
2076 }
2077
2078 uint32_t appId = lua_tointeger(L, index++);
2079
2080 HTTPListElement *element = calloc(1, sizeof(*element));
2081 if (element == NULL)
2082 {
2083 _dpd.errMsg( "Failed to allocate HTTP list element memory.");
2084 free(pattern_str);
2085 return 0;
2086 }
2087
2088 DetectorHTTPPattern *pattern = &element->detectorHTTPPattern;
2089 tAppIdConfig *pConfig = detectorUserData->pDetector->pAppidNewConfig;
2090
2091 pattern->seq = seq;
2092 pattern->service_id = appGetAppFromServiceId(service_id, pConfig);
2093 pattern->client_app = appGetAppFromClientId(client_app, pConfig);
2094 pattern->payload = appGetAppFromPayloadId(payload, pConfig);
2095 pattern->pattern = pattern_str;
2096 pattern->pattern_size = (int) pattern_size;
2097 pattern->appId = appId;
2098
2099 /* for apps that should not show up in 4.10 and ealier, we cannot include an entry in
2100 the legacy client app or payload tables. We will use the appId instead. This is only for
2101 user-agents that ID clients. if you want a user-agent to ID a payload, include it in the
2102 payload database. If you want a host pattern ID, use the other API. */
2103
2104 if (!service_id && !client_app && !payload && pType == 2)
2105 {
2106 pattern->client_app = appId;
2107 }
2108
2109 switch(pType)
2110 {
2111 case HTTP_PAYLOAD:
2112 element->next = pConfig->httpPatternLists.hostPayloadPatternList;
2113 pConfig->httpPatternLists.hostPayloadPatternList = element;
2114 break;
2115
2116 case HTTP_URL:
2117 element->next = pConfig->httpPatternLists.urlPatternList;
2118 pConfig->httpPatternLists.urlPatternList = element;
2119 break;
2120
2121 case HTTP_USER_AGENT:
2122 element->next = pConfig->httpPatternLists.clientAgentPatternList;
2123 pConfig->httpPatternLists.clientAgentPatternList = element;
2124 break;
2125 }
2126
2127 appInfoSetActive(pattern->service_id, true);
2128 appInfoSetActive(pattern->client_app, true);
2129 appInfoSetActive(pattern->payload, true);
2130 appInfoSetActive(appId, true);
2131
2132 return 0;
2133 }
2134
2135 /* On the lua side, this should look something like:
2136 addSSLCertPattern(<appId>, '<pattern string>' )
2137 */
2138 int Detector_addSSLCertPattern (lua_State *L)
2139 {
2140 uint8_t *pattern_str;
2141 size_t pattern_size;
2142 int index = 1;
2143 uint8_t type;
2144 tAppId app_id;
2145
2146 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
2147 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
2148 {
2149 _dpd.errMsg( "Invalid SSL detector user data or context.");
2150 return 0;
2151 }
2152
2153 type = lua_tointeger(L, index++);
2154 app_id = (tAppId) lua_tointeger(L, index++);
2155
2156 pattern_size = 0;
2157 const char *tmpString = lua_tolstring(L, index++, &pattern_size);
2158 if (!tmpString || !pattern_size)
2159 {
2160 _dpd.errMsg( "Invalid SSL Host pattern string");
2161 return 0;
2162 }
2163 pattern_str = (uint8_t *)strdup(tmpString);
2164 if (!pattern_str)
2165 {
2166 _dpd.errMsg( "Invalid SSL Host pattern string.");
2167 return 0;
2168 }
2169
2170 if (!ssl_add_cert_pattern(pattern_str, pattern_size, type, app_id, &detectorUserData->pDetector->pAppidNewConfig->serviceSslConfig))
2171 {
2172 free(pattern_str);
2173 _dpd.errMsg( "Failed to add an SSL pattern list member");
2174 return 0;
2175 }
2176
2177 appInfoSetActive(app_id, true);
2178 return 0;
2179 }
2180
2181 /* On the lua side, this should look something like:
2182 addDNSHostPattern(<appId>, '<pattern string>' )
2183 */
2184 int Detector_addDNSHostPattern (lua_State *L)
2185 {
2186 uint8_t *pattern_str;
2187 size_t pattern_size;
2188 int index = 1;
2189 uint8_t type;
2190 tAppId app_id;
2191
2192 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
2193 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
2194 {
2195 _dpd.errMsg( "LuaDetectorApi:Invalid DNS detector user data or context.");
2196 return 0;
2197 }
2198
2199 type = lua_tointeger(L, index++);
2200 app_id = (tAppId) lua_tointeger(L, index++);
2201
2202 pattern_size = 0;
2203 const char *tmpString = lua_tolstring(L, index++, &pattern_size);
2204 if (!tmpString || !pattern_size)
2205 {
2206 _dpd.errMsg( "LuaDetectorApi:Invalid DNS Host pattern string");
2207 return 0;
2208 }
2209 pattern_str = (uint8_t *)strdup(tmpString);
2210 if (!pattern_str)
2211 {
2212 _dpd.errMsg( "LuaDetectorApi:Invalid DNS Host pattern string.");
2213 return 0;
2214 }
2215
2216 if (!dns_add_host_pattern(pattern_str, pattern_size, type, app_id, &detectorUserData->pDetector->pAppidNewConfig->serviceDnsConfig))
2217 {
2218 free(pattern_str);
2219 _dpd.errMsg( "LuaDetectorApi:Failed to add an SSL pattern list member");
2220 }
2221
2222 return 0;
2223 }
2224
2225 static int Detector_addSSLCnamePattern (lua_State *L)
2226 {
2227 uint8_t *pattern_str;
2228 size_t pattern_size;
2229 int index = 1;
2230 uint8_t type;
2231 tAppId app_id;
2232
2233 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
2234 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
2235 {
2236 _dpd.errMsg( "Invalid SSL detector user data or context.");
2237 return 0;
2238 }
2239
2240 type = lua_tointeger(L, index++);
2241 app_id = (tAppId) lua_tointeger(L, index++);
2242
2243
2244 pattern_size = 0;
2245 const char *tmpString = lua_tolstring(L, index++, &pattern_size);
2246 if (!tmpString || !pattern_size)
2247 {
2248 _dpd.errMsg( "Invalid SSL Host pattern string");
2249 return 0;
2250 }
2251 pattern_str = (uint8_t *)strdup(tmpString);
2252 if (!pattern_str)
2253 {
2254 _dpd.errMsg( "Invalid SSL Host pattern string.");
2255 return 0;
2256 }
2257
2258 if (!ssl_add_cname_pattern(pattern_str, pattern_size, type, app_id, &detectorUserData->pDetector->pAppidNewConfig->serviceSslConfig))
2259 {
2260 free(pattern_str);
2261 _dpd.errMsg( "Failed to add an SSL pattern list member");
2262 return 0;
2263 }
2264
2265 appInfoSetActive(app_id, true);
2266 return 0;
2267 }
2268
2269 static int Detector_addHostPortApp (lua_State *L)
2270 {
2271 /*uint8_t *ipaddr_str; */
2272 size_t ipaddr_size;
2273 int index = 1;
2274 uint8_t type;
2275 tAppId app_id;
2276 struct in6_addr ip6Addr;
2277
2278 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
2279 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
2280 {
2281 _dpd.errMsg("%s: Invalid detector user data or context.\n",__func__);
2282 return 0;
2283 }
2284
2285 type = lua_tointeger(L, index++);
2286 app_id = (tAppId) lua_tointeger(L, index++);
2287
2288 ipaddr_size = 0;
2289 const char *tmpString = lua_tolstring(L, index++, &ipaddr_size);
2290 if (!tmpString || !ipaddr_size)
2291 {
2292 _dpd.errMsg("%s:Invalid ipaddr string\n",__func__);
2293 return 0;
2294 }
2295 if (!strchr(tmpString, ':'))
2296 {
2297 if (inet_pton(AF_INET, tmpString, &ip6Addr.s6_addr32[3]) <= 0)
2298 {
2299 _dpd.errMsg("%s: Invalid IP address: %s\n",__func__, tmpString);
2300 return 0;
2301 }
2302 ip6Addr.s6_addr32[0] = ip6Addr.s6_addr32[1] = 0;
2303 ip6Addr.s6_addr32[2] = ntohl(0x0000ffff);
2304 }
2305 else
2306 {
2307 if (inet_pton(AF_INET6, tmpString, &ip6Addr) <= 0)
2308 {
2309 _dpd.errMsg("%s: Invalid IP address: %s\n",__func__, tmpString);
2310 return 0;
2311 }
2312 }
2313 unsigned port = lua_tointeger(L, index++);
2314 unsigned proto = lua_tointeger(L, index++);
2315
2316 if (!hostPortAppCacheAdd(&ip6Addr, (uint16_t)port, (uint16_t)proto, type, app_id, detectorUserData->pDetector->pAppidNewConfig))
2317 {
2318 _dpd.errMsg("%s:Failed to backend call\n",__func__);
2319 }
2320
2321 return 0;
2322 }
2323
2324 static int Detector_addHostPortAppDynamic (lua_State *L)
2325 {
2326 /*uint8_t *ipaddr_str; */
2327 size_t ipaddr_size;
2328 int index = 1;
2329 uint8_t type;
2330 tAppId app_id;
2331 struct in6_addr ip6Addr;
2332
2333 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
2334 if (!detectorUserData)
2335 {
2336 _dpd.errMsg("%s: Invalid detector user data.\n",__func__);
2337 return 0;
2338 }
2339
2340 type = lua_tointeger(L, index++);
2341 app_id = (tAppId) lua_tointeger(L, index++);
2342
2343 ipaddr_size = 0;
2344 const char *tmpString = lua_tolstring(L, index++, &ipaddr_size);
2345 if (!tmpString || !ipaddr_size)
2346 {
2347 _dpd.errMsg("%s:Invalid ipaddr string\n",__func__);
2348 return 0;
2349 }
2350 if (!strchr(tmpString, ':'))
2351 {
2352 if (inet_pton(AF_INET, tmpString, &ip6Addr.s6_addr32[3]) <= 0)
2353 {
2354 _dpd.errMsg("%s: Invalid IP address: %s\n",__func__, tmpString);
2355 return 0;
2356 }
2357 ip6Addr.s6_addr32[0] = ip6Addr.s6_addr32[1] = 0;
2358 ip6Addr.s6_addr32[2] = ntohl(0x0000ffff);
2359 }
2360 else
2361 {
2362 if (inet_pton(AF_INET6, tmpString, &ip6Addr) <= 0)
2363 {
2364 _dpd.errMsg("%s: Invalid IP address: %s\n",__func__, tmpString);
2365 return 0;
2366 }
2367 }
2368 unsigned port = lua_tointeger(L, index++);
2369 unsigned proto = lua_tointeger(L, index++);
2370
2371 if (!hostPortAppCacheDynamicAdd(&ip6Addr, (uint16_t)port, (uint16_t)proto, type, app_id, true))
2372 {
2373 _dpd.errMsg("%s:Failed to backend call\n",__func__);
2374 }
2375
2376 return 0;
2377 }
2378
2379 static int Detector_addContentTypePattern(lua_State *L)
2380 {
2381 uint8_t *pattern;
2382 tAppId appId;
2383 int index = 1;
2384
2385 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
2386
2387 if (!detectorUserData)
2388 {
2389 _dpd.errMsg( "Invalid HTTP detector user data addContentTypePattern.");
2390 return 0;
2391 }
2392
2393 size_t stringSize = 0;
2394 const char *tmpString = lua_tolstring(L, index++, &stringSize);
2395 if (!tmpString || !stringSize)
2396 {
2397 _dpd.errMsg( "Invalid HTTP Header string");
2398 return 0;
2399 }
2400 pattern = (uint8_t *)strdup(tmpString);
2401 if (!pattern)
2402 {
2403 _dpd.errMsg( "Failed to allocate Content Type pattern string.");
2404 return 0;
2405 }
2406
2407 appId = lua_tointeger(L, index++);
2408
2409 if (detectorUserData->pDetector->validateParams.pkt)
2410 {
2411 _dpd.errMsg("Invalid detector context addSipUserAgent: appId %d\n",appId);
2412 free(pattern);
2413 return 0;
2414 }
2415
2416 HTTPListElement *element = calloc(1, sizeof(*element));
2417 if (!element)
2418 {
2419 _dpd.errMsg( "Failed to allocate HTTP list element memory.");
2420 free(pattern);
2421 return 0;
2422 }
2423
2424 DetectorHTTPPattern *detector = &element->detectorHTTPPattern;
2425 tAppIdConfig *pConfig = detectorUserData->pDetector->pAppidNewConfig;
2426
2427 detector->pattern = pattern;
2428 detector->pattern_size = strlen((char *)pattern);
2429 detector->appId = appId;
2430
2431 element->next = pConfig->httpPatternLists.contentTypePatternList;
2432 pConfig->httpPatternLists.contentTypePatternList = element;
2433
2434 appInfoSetActive(appId, true);
2435
2436 return 0;
2437 }
2438
2439 static inline int GetDetectorUserData(lua_State *L, int index,
2440 DetectorUserData **detector_user_data, const char *errorString)
2441 {
2442 // Verify detector user data and that we are not in packet context
2443 *detector_user_data = checkDetectorUserData(L, index);
2444 if (!*detector_user_data || (*detector_user_data)->pDetector->validateParams.pkt)
2445 {
2446 _dpd.errMsg(errorString);
2447 return -1;
2448 }
2449 return 0;
2450 }
2451
2452 static int detector_create_chp_app(DetectorUserData *detectorUserData, tAppId appIdInstance,
2453 unsigned app_type_flags, int num_matches)
2454 {
2455 CHPApp *new_app = (CHPApp *)calloc(1,sizeof(CHPApp));
2456 if (!new_app)
2457 {
2458 _dpd.errMsg( "LuaDetectorApi:Failed to allocate CHP app memory.");
2459 return -1;
2460 }
2461 new_app->appIdInstance = appIdInstance;
2462 new_app->app_type_flags = app_type_flags;
2463 new_app->num_matches = num_matches;
2464
2465 if (sfxhash_add(detectorUserData->pDetector->pAppidNewConfig->CHP_glossary, &(new_app->appIdInstance), new_app))
2466 {
2467 _dpd.errMsg( "LuaDetectorApi:Failed to add CHP for appId %d, instance %d", CHP_APPIDINSTANCE_TO_ID(appIdInstance), CHP_APPIDINSTANCE_TO_INSTANCE(appIdInstance));
2468 free(new_app);
2469 return -1;
2470 }
2471 return 0;
2472 }
2473
2474 static int Detector_CHPCreateApp (lua_State *L)
2475 {
2476 DetectorUserData *detectorUserData;
2477 tAppId appId;
2478 unsigned app_type_flags;
2479 int num_matches;
2480
2481 tAppId appIdInstance;
2482
2483 int index = 1;
2484
2485 if (GetDetectorUserData(L, index++, &detectorUserData,
2486 "LuaDetectorApi:Invalid HTTP detector user data in CHPCreateApp."))
2487 return 0;
2488
2489 appId = lua_tointeger(L, index++);
2490 appIdInstance = CHP_APPID_SINGLE_INSTANCE(appId); // Last instance for the old API
2491
2492 app_type_flags = lua_tointeger(L, index++);
2493 num_matches = lua_tointeger(L, index++);
2494
2495 // We only want one of these for each appId.
2496 if (sfxhash_find(detectorUserData->pDetector->pAppidNewConfig->CHP_glossary, &appIdInstance))
2497 {
2498 _dpd.errMsg( "LuaDetectorApi:Attempt to add more than one CHP for appId %d - use CHPMultiCreateApp", appId);
2499 return 0;
2500 }
2501
2502 detector_create_chp_app(detectorUserData, appIdInstance, app_type_flags, num_matches);
2503 return 0;
2504 }
2505
2506 static inline int CHPGetKeyPatternBoolean(lua_State *L, int index)
2507 {
2508 return (0 != lua_tointeger(L, index));
2509 }
2510
2511 static inline int CHPGetPatternType(lua_State *L, int index, PatternType *pattern_type)
2512 {
2513 *pattern_type = (PatternType) lua_tointeger(L, index);
2514 if(*pattern_type < AGENT_PT || *pattern_type > MAX_PATTERN_TYPE)
2515 {
2516 _dpd.errMsg( "LuaDetectorApi:Invalid CHP Action pattern type.");
2517 return -1;
2518 }
2519 return 0;
2520 }
2521
2522 static inline int CHPGetPatternDataAndSize(lua_State *L, int index, char **pattern_data, size_t *pattern_size)
2523 {
2524 const char *tmpString = NULL; // Lua owns this pointer
2525 *pattern_size = 0;
2526 *pattern_data = NULL;
2527 tmpString = lua_tolstring(L, index, &*pattern_size);
2528 if(!tmpString || !*pattern_size || !(*pattern_data = strdup(tmpString))) // non-empty pattern required
2529 {
2530 if (*pattern_size) // implies strdup() failed
2531 _dpd.errMsg( "LuaDetectorApi:CHP Action PATTERN string mem alloc failed.");
2532 else
2533 _dpd.errMsg( "LuaDetectorApi:Invalid CHP Action PATTERN string."); // empty string in Lua code - bad
2534 return -1;
2535 }
2536 return 0;
2537 }
2538
2539 static inline int CHPGetActionType(lua_State *L, int index, ActionType *action_type)
2540 {
2541 *action_type = (ActionType) lua_tointeger(L, index);
2542 if (*action_type < NO_ACTION || *action_type > MAX_ACTION_TYPE)
2543 {
2544 _dpd.errMsg( "LuaDetectorApi:Incompatible CHP Action type, might be for a later version.");
2545 return -1;
2546 }
2547 return 0;
2548 }
2549
2550 static inline int CHPGetActionData(lua_State *L, int index, char **action_data)
2551 {
2552 // An empty string is translated into a NULL pointer because the action data is optional
2553 const char *tmpString = NULL; // Lua owns this pointer
2554 size_t action_data_size = 0;
2555 *action_data = NULL;
2556 tmpString = lua_tolstring(L, index, &action_data_size);
2557 if (action_data_size)
2558 {
2559 if(!(*action_data = strdup(tmpString)))
2560 {
2561 _dpd.errMsg( "LuaDetectorApi:Action DATA string mem alloc failed.");
2562 return -1;
2563 }
2564 }
2565 return 0;
2566 }
2567
2568 static int detector_add_chp_action(DetectorUserData *detectorUserData,
2569 tAppId appIdInstance, int isKeyPattern, PatternType patternType,
2570 size_t patternSize, char *patternData, ActionType actionType, char *optionalActionData)
2571 {
2572 uint precedence;
2573 CHPListElement *tmp_chpa, *prev_chpa, *chpa;
2574 CHPApp *chpapp;
2575 tAppIdConfig *pConfig = detectorUserData->pDetector->pAppidNewConfig;
2576
2577 //find the CHP App for this
2578 if (!(chpapp = sfxhash_find(detectorUserData->pDetector->pAppidNewConfig->CHP_glossary, &appIdInstance)))
2579 {
2580 _dpd.errMsg( "LuaDetectorApi:Invalid attempt to add a CHP action for unknown appId %d, instance %d. - pattern:\"%s\" - action \"%s\"\n",
2581 CHP_APPIDINSTANCE_TO_ID(appIdInstance), CHP_APPIDINSTANCE_TO_INSTANCE(appIdInstance),
2582 patternData, optionalActionData ? optionalActionData : "");
2583 free(patternData);
2584 if (optionalActionData) free(optionalActionData);
2585 return 0;
2586 }
2587
2588 if (isKeyPattern)
2589 {
2590 chpapp->key_pattern_count++;
2591 chpapp->key_pattern_length_sum += patternSize;
2592 }
2593
2594 if (chpapp->ptype_scan_counts[patternType] == 0)
2595 chpapp->num_scans++;
2596 precedence = chpapp->ptype_scan_counts[patternType]++; // The increment is for the sake of the precedence. ptype_scan_counts means "The scan DOES count toward the total required."
2597 // at runtime we'll want to know how many of each type of pattern we are looking for.
2598 if (actionType == REWRITE_FIELD || actionType == INSERT_FIELD)
2599 {
2600 if (!appInfoEntryFlagGet(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SUPPORTED_SEARCH, pConfig))
2601 {
2602 _dpd.errMsg( "LuaDetectorApi: CHP action type, %d, requires previous use of action type, %d, (see appId %d, pattern=\"%s\").\n",
2603 actionType, GET_OFFSETS_FROM_REBUILT, CHP_APPIDINSTANCE_TO_ID(appIdInstance), patternData);
2604 free(patternData);
2605 if (optionalActionData) free(optionalActionData);
2606 return 0;
2607 }
2608 switch (patternType)
2609 {
2610 // permitted pattern type (modifiable HTTP/SPDY request field)
2611 case AGENT_PT:
2612 case HOST_PT:
2613 case REFERER_PT:
2614 case URI_PT:
2615 case COOKIE_PT:
2616 break;
2617 default:
2618 _dpd.errMsg( "LuaDetectorApi: CHP action type, %d, on unsupported pattern type, %d, (see appId %d, pattern=\"%s\").\n",
2619 actionType, patternType, CHP_APPIDINSTANCE_TO_ID(appIdInstance), patternData);
2620 free(patternData);
2621 if (optionalActionData) free(optionalActionData);
2622 return 0;
2623 }
2624 }
2625 else if (actionType != ALTERNATE_APPID && actionType != DEFER_TO_SIMPLE_DETECT)
2626 chpapp->ptype_req_counts[patternType]++;
2627
2628 chpa = (CHPListElement*)calloc(1,sizeof(CHPListElement));
2629 if (!chpa)
2630 {
2631 _dpd.errMsg( "LuaDetectorApi: Failed to allocate CHP action memory.\n");
2632 free(patternData);
2633 if (optionalActionData) free(optionalActionData);
2634 return 0;
2635 }
2636 chpa->chp_action.appIdInstance = appIdInstance;
2637 chpa->chp_action.precedence = precedence;
2638 chpa->chp_action.key_pattern = isKeyPattern;
2639 chpa->chp_action.ptype = patternType;
2640 chpa->chp_action.psize = patternSize;
2641 chpa->chp_action.pattern = patternData;
2642 chpa->chp_action.action = actionType;
2643 chpa->chp_action.action_data = optionalActionData;
2644 chpa->chp_action.chpapp = chpapp; // link this struct to the Glossary entry
2645
2646 tmp_chpa = pConfig->httpPatternLists.chpList;
2647 if (!tmp_chpa) pConfig->httpPatternLists.chpList = chpa;
2648 else
2649 {
2650 while (tmp_chpa->next)
2651 tmp_chpa = tmp_chpa->next;
2652 tmp_chpa->next = chpa;
2653 }
2654
2655 /* Set the safe-search bits in the appId entry */
2656 if (actionType == GET_OFFSETS_FROM_REBUILT)
2657 {
2658 /* This is a search engine and it is SUPPORTED for safe-search packet rewrite */
2659 appInfoEntryFlagSet(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SEARCH_ENGINE | APPINFO_FLAG_SUPPORTED_SEARCH, pConfig);
2660 }
2661 else if (actionType == SEARCH_UNSUPPORTED)
2662 {
2663 /* This is a search engine and it is UNSUPPORTED for safe-search packet rewrite */
2664 appInfoEntryFlagSet(CHP_APPIDINSTANCE_TO_ID(appIdInstance), APPINFO_FLAG_SEARCH_ENGINE, pConfig);
2665 }
2666 else if (actionType == DEFER_TO_SIMPLE_DETECT && strcmp(patternData,"<ignore-all-patterns>") == 0)
2667 {
2668 // Walk the list of all the patterns we have inserted, searching for this appIdInstance and free them.
2669 // The purpose is for the 14 and 15 to be used together to only set the APPINFO_FLAG_SEARCH_ENGINE flag
2670 // If the reserved pattern is not used, it is a mixed use case and should just behave normally.
2671 prev_chpa = NULL;
2672 tmp_chpa = pConfig->httpPatternLists.chpList;
2673 while (tmp_chpa)
2674 {
2675 if (tmp_chpa->chp_action.appIdInstance == appIdInstance)
2676 {
2677 // advance the tmp_chpa pointer by removing the item pointed to. Keep prev_chpa unchanged.
2678
2679 // 1) unlink the struct, 2) free strings and then 3) free the struct.
2680 chpa = tmp_chpa; // preserve this pointer to be freed at the end.
2681 if (prev_chpa == NULL)
2682 {
2683 // Remove from head
2684 pConfig->httpPatternLists.chpList = tmp_chpa->next;
2685 tmp_chpa = pConfig->httpPatternLists.chpList;
2686 }
2687 else
2688 {
2689 // Remove from middle of list.
2690 prev_chpa->next = tmp_chpa->next;
2691 tmp_chpa = prev_chpa->next;
2692 }
2693 free(chpa->chp_action.pattern);
2694 if (chpa->chp_action.action_data) free(chpa->chp_action.action_data);
2695 free(chpa);
2696 }
2697 else
2698 {
2699 // advance both pointers
2700 prev_chpa = tmp_chpa;
2701 tmp_chpa = tmp_chpa->next;
2702 }
2703 }
2704 }
2705 return 0;
2706 }
2707 static int Detector_CHPAddAction (lua_State *L)
2708 {
2709 DetectorUserData *detectorUserData;
2710 int key_pattern;
2711 PatternType ptype;
2712 size_t psize;
2713 char *pattern;
2714 ActionType action;
2715 char *action_data;
2716
2717 tAppId appIdInstance;
2718 tAppId appId;
2719
2720 int index = 1;
2721
2722 if (GetDetectorUserData(L, index++, &detectorUserData,
2723 "LuaDetectorApi:Invalid HTTP detector user data in CHPAddAction."))
2724 return 0;
2725
2726 // Parameter 1
2727 appId = lua_tointeger(L, index++);
2728 appIdInstance = CHP_APPID_SINGLE_INSTANCE(appId); // Last instance for the old API
2729
2730 // Parameter 2
2731 key_pattern = CHPGetKeyPatternBoolean(L, index++);
2732
2733 // Parameter 3
2734 if (CHPGetPatternType(L, index++, &ptype))
2735 return 0;
2736
2737 // Parameter 4
2738 if (CHPGetPatternDataAndSize(L, index++, &pattern, &psize))
2739 return 0;
2740
2741 // Parameter 5
2742 if (CHPGetActionType(L, index++, &action))
2743 {
2744 free(pattern);
2745 return 0;
2746 }
2747
2748 // Parameter 6
2749 if (CHPGetActionData(L, index++, &action_data))
2750 {
2751 free(pattern);
2752 return 0;
2753 }
2754
2755 return detector_add_chp_action(detectorUserData, appIdInstance, key_pattern, ptype,
2756 psize, pattern, action, action_data);
2757 }
2758
2759 static int Detector_CHPMultiCreateApp (lua_State *L)
2760 {
2761 DetectorUserData *detectorUserData;
2762 tAppId appId;
2763 unsigned app_type_flags;
2764 int num_matches;
2765
2766 tAppId appIdInstance;
2767 int instance;
2768
2769 int index = 1;
2770
2771 if (GetDetectorUserData(L, index++, &detectorUserData,
2772 "LuaDetectorApi:Invalid HTTP detector user data in CHPMultiCreateApp."))
2773 return 0;
2774
2775 appId = lua_tointeger(L, index++);
2776 app_type_flags = lua_tointeger(L, index++);
2777 num_matches = lua_tointeger(L, index++);
2778
2779 for (instance=0; instance < CHP_APPID_INSTANCE_MAX; instance++ )
2780 {
2781 appIdInstance = (appId << CHP_APPID_BITS_FOR_INSTANCE) + instance;
2782 if (sfxhash_find(detectorUserData->pDetector->pAppidNewConfig->CHP_glossary, &appIdInstance))
2783 continue;
2784 break;
2785 }
2786
2787 // We only want a maximum of these for each appId.
2788 if (instance == CHP_APPID_INSTANCE_MAX)
2789 {
2790 _dpd.errMsg( "LuaDetectorApi:Attempt to create more than %d CHP for appId %d", CHP_APPID_INSTANCE_MAX, appId);
2791 return 0;
2792 }
2793
2794 if (detector_create_chp_app(detectorUserData, appIdInstance, app_type_flags, num_matches))
2795 return 0;
2796
2797 lua_pushnumber(L, appIdInstance);
2798 return 1;
2799 }
2800
2801
2802 static int Detector_CHPMultiAddAction (lua_State *L)
2803 {
2804 DetectorUserData *detectorUserData;
2805 int key_pattern;
2806 PatternType ptype;
2807 size_t psize;
2808 char *pattern;
2809 ActionType action;
2810 char *action_data;
2811
2812 tAppId appIdInstance;
2813
2814 int index = 1;
2815
2816 if (GetDetectorUserData(L, index++, &detectorUserData,
2817 "LuaDetectorApi:Invalid HTTP detector user data in CHPMultiAddAction."))
2818 return 0;
2819
2820 // Parameter 1
2821 appIdInstance = lua_tointeger(L, index++);
2822
2823 // Parameter 2
2824 key_pattern = CHPGetKeyPatternBoolean(L, index++);
2825
2826 // Parameter 3
2827 if (CHPGetPatternType(L, index++, &ptype))
2828 return 0;
2829
2830 // Parameter 4
2831 if (CHPGetPatternDataAndSize(L, index++, &pattern, &psize))
2832 return 0;
2833
2834 // Parameter 5
2835 if (CHPGetActionType(L, index++, &action))
2836 {
2837 free(pattern);
2838 return 0;
2839 }
2840
2841 // Parameter 6
2842 if (CHPGetActionData(L, index++, &action_data))
2843 {
2844 free(pattern);
2845 return 0;
2846 }
2847
2848 return detector_add_chp_action(detectorUserData, appIdInstance, key_pattern, ptype,
2849 psize, pattern, action, action_data);
2850 }
2851
2852 static int Detector_portOnlyService (lua_State *L)
2853 {
2854 int index = 1;
2855
2856 // Verify detector user data and that we are not in packet context
2857 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
2858 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
2859 {
2860 _dpd.errMsg( "LuaDetectorApi:Invalid HTTP detector user data in addPortOnlyService.");
2861 return 0;
2862 }
2863
2864 tAppId appId = lua_tointeger(L, index++);
2865 u_int16_t port = lua_tointeger(L, index++);
2866 u_int8_t protocol = lua_tointeger(L, index++);
2867
2868 if (port == 0)
2869 detectorUserData->pDetector->pAppidNewConfig->ip_protocol[protocol] = appId;
2870 else if (protocol == 6)
2871 detectorUserData->pDetector->pAppidNewConfig->tcp_port_only[port] = appId;
2872 else if (protocol == 17)
2873 detectorUserData->pDetector->pAppidNewConfig->udp_port_only[port] = appId;
2874
2875 return 0;
2876 }
2877
2878 /* Add a length-based detector. This is done by adding a new length sequence
2879 * to the cache. Note that this does not require a validate and is only used
2880 * as a fallback identification.
2881 *
2882 * @param lua_State* - Lua state variable.
2883 * @param appId/stack - App ID to use for this detector.
2884 * @param proto/stack - Protocol (IPPROTO_TCP/DC.ipproto.tcp (6) or
2885 * IPPROTO_UDP/DC.ipproto.udp (17)).
2886 * @param sequence_cnt/stack - Number of elements in sequence below (max of
2887 * LENGTH_SEQUENCE_CNT_MAX).
2888 * @param sequence_str/stack - String that defines direction/length sequence.
2889 * - Example: "I/8,R/512,I/512,R/1024,I/1024"
2890 * - Direction: I(nitiator) or R(esponder).
2891 * - Length : Payload size (bytes) (> 0).
2892 * @return int - Number of elements on stack, which is always 1.
2893 * @return status/stack - 0 if successful, -1 otherwise.
2894 */
2895 static int Detector_lengthAppCacheAdd(lua_State *L)
2896 {
2897 int i;
2898 const char *str_ptr;
2899 uint16_t length;
2900 tLengthKey length_sequence;
2901 int index = 1;
2902
2903 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
2904 if (detectorUserData == NULL)
2905 {
2906 _dpd.errMsg( "LuaDetectorApi:Invalid detector user data!");
2907 lua_pushnumber(L, -1);
2908 return 1;
2909 }
2910
2911 tAppId appId = lua_tonumber(L, index++);
2912 uint8_t proto = lua_tonumber(L, index++);
2913 uint8_t sequence_cnt = lua_tonumber(L, index++);
2914 const char *sequence_str = lua_tostring(L, index++);
2915
2916 if (((proto != IPPROTO_TCP) && (proto != IPPROTO_UDP))
2917 || ((sequence_cnt == 0) || (sequence_cnt > LENGTH_SEQUENCE_CNT_MAX))
2918 || ((sequence_str == NULL) || (strlen(sequence_str) == 0)))
2919 {
2920 _dpd.errMsg( "LuaDetectorApi:Invalid input (%d,%u,%u,\"%s\")!",
2921 appId, (unsigned)proto, (unsigned)sequence_cnt, sequence_str ?: "");
2922 lua_pushnumber(L, -1);
2923 return 1;
2924 }
2925
2926 memset(&length_sequence, 0, sizeof(length_sequence));
2927
2928 length_sequence.proto = proto;
2929 length_sequence.sequence_cnt = sequence_cnt;
2930
2931 str_ptr = sequence_str;
2932 for (i = 0; i < sequence_cnt; i++)
2933 {
2934 int last_one;
2935
2936 switch (*str_ptr)
2937 {
2938 case 'I':
2939 length_sequence.sequence[i].direction = APP_ID_FROM_INITIATOR;
2940 break;
2941 case 'R':
2942 length_sequence.sequence[i].direction = APP_ID_FROM_RESPONDER;
2943 break;
2944 default:
2945 _dpd.errMsg( "LuaDetectorApi:Invalid sequence string (\"%s\")!",
2946 sequence_str);
2947 lua_pushnumber(L, -1);
2948 return 1;
2949 }
2950 str_ptr++;
2951
2952 if (*str_ptr != '/')
2953 {
2954 _dpd.errMsg( "LuaDetectorApi:Invalid sequence string (\"%s\")!",
2955 sequence_str);
2956 lua_pushnumber(L, -1);
2957 return 1;
2958 }
2959 str_ptr++;
2960
2961 length = (uint16_t)atoi(str_ptr);
2962 if (length == 0)
2963 {
2964 _dpd.errMsg( "LuaDetectorApi:Invalid sequence string (\"%s\")!",
2965 sequence_str);
2966 lua_pushnumber(L, -1);
2967 return 1;
2968 }
2969 length_sequence.sequence[i].length = length;
2970
2971 while ((*str_ptr != ',') && (*str_ptr != 0))
2972 {
2973 str_ptr++;
2974 }
2975
2976 last_one = (i == (sequence_cnt - 1));
2977 if ( (!last_one && (*str_ptr != ','))
2978 || (last_one && (*str_ptr != 0)))
2979 {
2980 _dpd.errMsg( "LuaDetectorApi:Invalid sequence string (\"%s\")!",
2981 sequence_str);
2982 lua_pushnumber(L, -1);
2983 return 1;
2984 }
2985 str_ptr++;
2986 }
2987
2988 if (!lengthAppCacheAdd(&length_sequence, appId, detectorUserData->pDetector->pAppidNewConfig))
2989 {
2990 _dpd.errMsg( "LuaDetectorApi:Could not add entry to cache!");
2991 lua_pushnumber(L, -1);
2992 return 1;
2993 }
2994
2995 lua_pushnumber(L, 0);
2996 return 1;
2997 }
2998
2999 static int Detector_AFAddApp (lua_State *L)
3000 {
3001 int index = 1;
3002 AFElement val;
3003
3004 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
3005 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
3006 {
3007 _dpd.errMsg( "LuaDetectorApi:Invalid HTTP detector user data in AFAddApp.");
3008 return 0;
3009 }
3010
3011 tAppId indicator = lua_tointeger(L, index++);
3012 tAppId forecast = lua_tointeger(L, index++);
3013 tAppId target = lua_tointeger(L, index++);
3014
3015 if (sfxhash_find(detectorUserData->pDetector->pAppidNewConfig->AF_indicators, &indicator))
3016 {
3017 _dpd.errMsg( "LuaDetectorApi:Attempt to add more than one AFElement per appId %d", indicator);
3018 return 0;
3019 }
3020
3021 val.indicator = indicator;
3022 val.forecast = forecast;
3023 val.target = target;
3024
3025 if (sfxhash_add(detectorUserData->pDetector->pAppidNewConfig->AF_indicators, &indicator, &val))
3026 {
3027 _dpd.errMsg( "LuaDetectorApi:Failed to add AFElement for appId %d", indicator);
3028 return 0;
3029 }
3030
3031 return 0;
3032 }
3033
3034 static int Detector_addAppUrl(lua_State *L)
3035 {
3036 int index = 1;
3037 DetectorAppUrlPattern **tmp;
3038 const char *tmpString;
3039
3040 /* Verify detector user data and that we are not in packet context */
3041 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
3042 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
3043 {
3044 _dpd.errMsg( "Invalid HTTP detector user data in addAppUrl.");
3045 return 0;
3046 }
3047
3048 u_int32_t service_id = lua_tointeger(L, index++);
3049 u_int32_t client_id = lua_tointeger(L, index++);
3050 lua_tointeger(L, index++); // client_app_type
3051 u_int32_t payload_id = lua_tointeger(L, index++);
3052 lua_tointeger(L, index++); // payload_type
3053
3054 if (detectorUserData->pDetector->validateParams.pkt)
3055 {
3056 _dpd.errMsg("Invalid HTTP detector context addAppUrl: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
3057 return 0;
3058 }
3059
3060 /* Verify that host pattern is a valid string */
3061 size_t hostPatternSize = 0;
3062 u_int8_t* hostPattern = NULL;
3063 tmpString = lua_tolstring(L, index++, &hostPatternSize);
3064 if(!tmpString || !hostPatternSize)
3065 {
3066 _dpd.errMsg( "Invalid host pattern string:service_id %u; client_id %u; payload_id %u\n.",service_id, client_id, payload_id);
3067 return 0;
3068 }
3069 else if (!(hostPattern = (u_int8_t *)strdup(tmpString)))
3070 {
3071 _dpd.errMsg( "Failed to duplicate host pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
3072 return 0;
3073 }
3074
3075 /* Verify that path pattern is a valid string */
3076 size_t pathPatternSize = 0;
3077 u_int8_t* pathPattern = NULL;
3078 tmpString = lua_tolstring(L, index++, &pathPatternSize);
3079 if(!tmpString || !pathPatternSize)
3080 {
3081 _dpd.errMsg( "Invalid path pattern string: service_id %u; client_id %u; payload_id %u\n.",service_id, client_id, payload_id);
3082 free(hostPattern);
3083 return 0;
3084 }
3085 else if (!(pathPattern = (u_int8_t *)strdup(tmpString)))
3086 {
3087 _dpd.errMsg( "Failed to duplicate path pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
3088 free(hostPattern);
3089 return 0;
3090 }
3091
3092 /* Verify that scheme pattern is a valid string */
3093 size_t schemePatternSize;
3094 u_int8_t* schemePattern = NULL;
3095 tmpString = lua_tolstring(L, index++, &schemePatternSize);
3096 if(!tmpString || !schemePatternSize)
3097 {
3098 _dpd.errMsg( "Invalid scheme pattern string: service_id %u; client_id %u; payload_id %u\n.",service_id, client_id, payload_id);
3099 free(pathPattern);
3100 free(hostPattern);
3101 return 0;
3102 }
3103 else if (!(schemePattern = (u_int8_t*) strdup(tmpString)))
3104 {
3105 _dpd.errMsg( "Failed to duplicate scheme pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
3106 free(pathPattern);
3107 free(hostPattern);
3108 return 0;
3109 }
3110
3111 /* Verify that query pattern is a valid string */
3112 size_t queryPatternSize;
3113 u_int8_t* queryPattern = NULL;
3114 tmpString = lua_tolstring(L, index++, &queryPatternSize);
3115 if(tmpString && queryPatternSize)
3116 {
3117 if (!(queryPattern = (u_int8_t*) strdup(tmpString)))
3118 {
3119 _dpd.errMsg( "Invalid query pattern string.");
3120 free(hostPattern);
3121 free(pathPattern);
3122 free(schemePattern);
3123 return 0;
3124 }
3125 }
3126
3127 u_int32_t appId = lua_tointeger(L, index++);
3128
3129 /* Allocate memory for data structures */
3130 DetectorAppUrlPattern *pattern = malloc(sizeof(DetectorAppUrlPattern));
3131 if (!pattern)
3132 {
3133 _dpd.errMsg( "Failed to allocate HTTP pattern memory.");
3134 free(hostPattern);
3135 free(pathPattern);
3136 free(schemePattern);
3137 if (queryPattern) free(queryPattern);
3138 return 0;
3139 }
3140
3141 tAppIdConfig *pConfig = detectorUserData->pDetector->pAppidNewConfig;
3142
3143 pattern->userData.service_id = appGetAppFromServiceId(service_id, pConfig);
3144 pattern->userData.client_app = appGetAppFromClientId(client_id, pConfig);
3145 pattern->userData.payload = appGetAppFromPayloadId(payload_id, pConfig);
3146 pattern->userData.appId = appId;
3147 pattern->userData.query.pattern = queryPattern;
3148 pattern->userData.query.patternSize = queryPatternSize;
3149 pattern->patterns.host.pattern = hostPattern;
3150 pattern->patterns.host.patternSize = (int) hostPatternSize;
3151 pattern->patterns.path.pattern = pathPattern;
3152 pattern->patterns.path.patternSize = (int) pathPatternSize;
3153 pattern->patterns.scheme.pattern = schemePattern;
3154 pattern->patterns.scheme.patternSize = (int) schemePatternSize;
3155
3156 DetectorAppUrlList *urlList = &pConfig->httpPatternLists.appUrlList;
3157
3158 /**first time usedCount and allocatedCount are both 0, urlPattern will be NULL.
3159 * This case is same as malloc. In case of error, realloc will return NULL, and
3160 * original urlPattern buffer is left untouched.
3161 */
3162 if (urlList->usedCount == urlList->allocatedCount)
3163 {
3164 tmp = realloc(urlList->urlPattern, (urlList->allocatedCount+URL_LIST_STEP_SIZE)*sizeof(*tmp));
3165 if (!tmp)
3166 {
3167 FreeDetectorAppUrlPattern(pattern);
3168 return 0;
3169 }
3170 urlList->urlPattern = tmp;
3171 urlList->allocatedCount += URL_LIST_STEP_SIZE;
3172 }
3173
3174 urlList->urlPattern[urlList->usedCount++] = pattern;
3175
3176 appInfoSetActive(pattern->userData.service_id, true);
3177 appInfoSetActive(pattern->userData.client_app, true);
3178 appInfoSetActive(pattern->userData.payload, true);
3179 appInfoSetActive(appId, true);
3180
3181 return 0;
3182 }
3183
3184 static int Detector_addRTMPUrl(lua_State *L)
3185 {
3186 int index = 1;
3187 DetectorAppUrlPattern **tmp;
3188 const char *tmpString;
3189
3190 /* Verify detector user data and that we are not in packet context */
3191 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
3192 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
3193 {
3194 _dpd.errMsg( "Invalid HTTP detector user data in addRTMPUrl.");
3195 return 0;
3196 }
3197
3198 u_int32_t service_id = lua_tointeger(L, index++);
3199 u_int32_t client_id = lua_tointeger(L, index++);
3200 lua_tointeger(L, index++); // client_app_type
3201 u_int32_t payload_id = lua_tointeger(L, index++);
3202 lua_tointeger(L, index++); // payload_type
3203
3204 if (detectorUserData->pDetector->validateParams.pkt)
3205 {
3206 _dpd.errMsg("Invalid HTTP detector context addRTMPUrl: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
3207 return 0;
3208 }
3209
3210 /* Verify that host pattern is a valid string */
3211 size_t hostPatternSize = 0;
3212 u_int8_t* hostPattern = NULL;
3213 tmpString = lua_tolstring(L, index++, &hostPatternSize);
3214 if(!tmpString || !hostPatternSize)
3215 {
3216 _dpd.errMsg( "Invalid host pattern string:service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
3217 return 0;
3218 }
3219 else if (!(hostPattern = (u_int8_t *)strdup(tmpString)))
3220 {
3221 _dpd.errMsg( "Failed to duplicate host pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
3222 return 0;
3223 }
3224
3225 /* Verify that path pattern is a valid string */
3226 size_t pathPatternSize = 0;
3227 u_int8_t* pathPattern = NULL;
3228 tmpString = lua_tolstring(L, index++, &pathPatternSize);
3229 if(!tmpString || !pathPatternSize)
3230 {
3231 _dpd.errMsg( "Invalid path pattern string: service_id %u; client_id %u; payload_id %u\n.",service_id, client_id, payload_id);
3232 free(hostPattern);
3233 return 0;
3234 }
3235 else if (!(pathPattern = (u_int8_t *)strdup(tmpString)))
3236 {
3237 _dpd.errMsg( "Failed to duplicate path pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
3238 free(hostPattern);
3239 return 0;
3240 }
3241
3242 /* Verify that scheme pattern is a valid string */
3243 size_t schemePatternSize;
3244 u_int8_t* schemePattern = NULL;
3245 tmpString = lua_tolstring(L, index++, &schemePatternSize);
3246 if(!tmpString || !schemePatternSize)
3247 {
3248 _dpd.errMsg( "Invalid scheme pattern string: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
3249 free(pathPattern);
3250 free(hostPattern);
3251 return 0;
3252 }
3253 else if (!(schemePattern = (u_int8_t*) strdup(tmpString)))
3254 {
3255 _dpd.errMsg( "Failed to duplicate scheme pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
3256 free(pathPattern);
3257 free(hostPattern);
3258 return 0;
3259 }
3260
3261 /* Verify that query pattern is a valid string */
3262 size_t queryPatternSize;
3263 u_int8_t* queryPattern = NULL;
3264 tmpString = lua_tolstring(L, index++, &queryPatternSize);
3265 if(tmpString && queryPatternSize)
3266 {
3267 if (!(queryPattern = (u_int8_t*) strdup(tmpString)))
3268 {
3269 _dpd.errMsg( "Invalid query pattern string.");
3270 free(hostPattern);
3271 free(pathPattern);
3272 free(schemePattern);
3273 return 0;
3274 }
3275 }
3276
3277 u_int32_t appId = lua_tointeger(L, index++);
3278
3279 /* Allocate memory for data structures */
3280 DetectorAppUrlPattern *pattern = malloc(sizeof(DetectorAppUrlPattern));
3281 if (!pattern)
3282 {
3283 _dpd.errMsg( "Failed to allocate HTTP pattern memory.");
3284 free(hostPattern);
3285 free(pathPattern);
3286 free(schemePattern);
3287 if (queryPattern) free(queryPattern);
3288 return 0;
3289 }
3290
3291 /* we want to put these patterns in just like for regular Urls, but we do NOT need legacy IDs for them.
3292 * so just use the appID for service, client, or payload ID */
3293 pattern->userData.service_id = service_id;
3294 pattern->userData.client_app = client_id;
3295 pattern->userData.payload = payload_id;
3296 pattern->userData.appId = appId;
3297 pattern->userData.query.pattern = queryPattern;
3298 pattern->userData.query.patternSize = queryPatternSize;
3299 pattern->patterns.host.pattern = hostPattern;
3300 pattern->patterns.host.patternSize = (int) hostPatternSize;
3301 pattern->patterns.path.pattern = pathPattern;
3302 pattern->patterns.path.patternSize = (int) pathPatternSize;
3303 pattern->patterns.scheme.pattern = schemePattern;
3304 pattern->patterns.scheme.patternSize = (int) schemePatternSize;
3305
3306 tAppIdConfig *pConfig = detectorUserData->pDetector->pAppidNewConfig;
3307 DetectorAppUrlList *urlList = &pConfig->httpPatternLists.RTMPUrlList;
3308
3309 /**first time usedCount and allocatedCount are both 0, urlPattern will be NULL.
3310 * This case is same as malloc. In case of error, realloc will return NULL, and
3311 * original urlPattern buffer is left untouched.
3312 */
3313 if (urlList->usedCount == urlList->allocatedCount)
3314 {
3315 tmp = realloc(urlList->urlPattern, (urlList->allocatedCount+URL_LIST_STEP_SIZE)*sizeof(*tmp));
3316 if (!tmp)
3317 {
3318 FreeDetectorAppUrlPattern(pattern);
3319 return 0;
3320 }
3321 urlList->urlPattern = tmp;
3322 urlList->allocatedCount += URL_LIST_STEP_SIZE;
3323 }
3324
3325 urlList->urlPattern[urlList->usedCount++] = pattern;
3326
3327 appInfoSetActive(pattern->userData.service_id, true);
3328 appInfoSetActive(pattern->userData.client_app, true);
3329 appInfoSetActive(pattern->userData.payload, true);
3330 appInfoSetActive(appId, true);
3331
3332 return 0;
3333 }
3334
3335 /*Lua should inject patterns in <clientAppId, clientVersion, multi-Pattern> format. */
3336 static int Detector_addSipUserAgent(lua_State *L)
3337 {
3338 int index = 1;
3339
3340 /* Verify detector user data and that we are not in packet context */
3341 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
3342 if (!detectorUserData)
3343 {
3344 _dpd.errMsg( "Invalid HTTP detector user data addSipUserAgent.");
3345 return 0;
3346 }
3347
3348 u_int32_t client_app = lua_tointeger(L, index++);
3349 const char *clientVersion = lua_tostring(L, index++);
3350 if(!clientVersion )
3351 {
3352 _dpd.errMsg( "Invalid sip client version string.");
3353 return 0;
3354 }
3355
3356 if (detectorUserData->pDetector->validateParams.pkt)
3357 {
3358 _dpd.errMsg("Invalid detector context addSipUserAgent: client_app %u\n",client_app);
3359 return 0;
3360 }
3361
3362 /* Verify that ua pattern is a valid string */
3363 const char* uaPattern = lua_tostring(L, index++);
3364 if(!uaPattern)
3365 {
3366 _dpd.errMsg( "Invalid sip ua pattern string.");
3367 return 0;
3368 }
3369
3370 sipUaPatternAdd(client_app, clientVersion, uaPattern, &detectorUserData->pDetector->pAppidNewConfig->detectorSipConfig);
3371
3372 appInfoSetActive(client_app, true);
3373
3374 return 0;
3375 }
3376
3377 static int openCreateApp(lua_State *L)
3378 {
3379 int index = 1;
3380 const char *tmpString;
3381
3382 /* Verify detector user data and that we are not in packet context */
3383 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
3384 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
3385 {
3386 _dpd.errMsg( "Invalid HTTP detector user data in addAppUrl.");
3387 return 0;
3388 }
3389
3390 /* Verify that host pattern is a valid string */
3391 size_t appNameLen = 0;
3392 tmpString = lua_tolstring(L, index++, &appNameLen);
3393 if(!tmpString || !appNameLen)
3394 {
3395 _dpd.errMsg( "Invalid appName string.");
3396 lua_pushnumber(L, APP_ID_NONE);
3397 return 1; /*number of results */
3398 }
3399
3400 AppInfoTableEntry *entry = appInfoEntryCreate(tmpString, detectorUserData->pDetector->pAppidNewConfig);
3401
3402 if (entry)
3403 {
3404 lua_pushnumber(L, entry->appId);
3405 return 1; /*number of results */
3406 }
3407
3408 lua_pushnumber(L, APP_ID_NONE);
3409 return 1; /*number of results */
3410 }
3411
3412 static int openAddClientApp(
3413 lua_State *L
3414 )
3415 {
3416 unsigned int serviceAppId, clientAppId;
3417 Detector *detector;
3418 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
3419
3420 serviceAppId = lua_tonumber(L, 2);
3421 clientAppId = lua_tonumber(L, 3);
3422
3423 /*check inputs and whether this function is called in context of a */
3424 /*packet */
3425 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
3426 {
3427 lua_pushnumber(L, -1);
3428 return 1;
3429 }
3430
3431 detector = detectorUserData->pDetector;
3432
3433 if (!detector->client.appModule.api)
3434 {
3435 lua_pushnumber(L, -1);
3436 return 1;
3437 }
3438
3439 detector->client.appModule.api->add_app(detector->validateParams.pkt, (APPID_SESSION_DIRECTION) detector->validateParams.dir, detector->pAppidActiveConfig, detector->validateParams.flowp, serviceAppId, clientAppId, "");
3440
3441 lua_pushnumber(L, 0);
3442 return 1;
3443 }
3444
3445 /** Add service id to a flow. Positive identification by a detector.
3446 *
3447 * @param Lua_State* - Lua state variable.
3448 * @param detector/stack - detector object
3449 * @param serviceId/stack - id of service postively identified on this flow.
3450 * @param vendorName/stack - name of vendor of service. This is optional.
3451 * @param version/stack - version of service. This is optional.
3452 * @return int - Number of elements on stack, which is always 1.
3453 * @return int/stack - values from enum SERVICE_RETCODE
3454 */
3455 static int openAddServiceApp(
3456 lua_State *L
3457 )
3458 {
3459 unsigned int serviceId, retValue = SERVICE_ENULL;
3460 Detector *detector;
3461 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
3462
3463 serviceId = lua_tonumber(L, 2);
3464
3465 if (!detectorUserData || !checkServiceElement(detectorUserData->pDetector)
3466 || !detectorUserData->pDetector->validateParams.pkt)
3467 {
3468 lua_pushnumber(L, SERVICE_ENULL);
3469 return 1;
3470 }
3471
3472 detector = detectorUserData->pDetector;
3473
3474 /*Phase2 - discuss RNAServiceSubtype will be maintained on lua side therefore the last parameter on the following call is NULL. */
3475 /*Subtype is not displayed on DC at present. */
3476 retValue = AppIdServiceAddService(detector->validateParams.flowp, detector->validateParams.pkt,
3477 detector->validateParams.dir, detector->server.pServiceElement,
3478 serviceId, NULL, NULL, NULL, NULL);
3479
3480 lua_pushnumber(L, retValue);
3481 return 1;
3482 }
3483
3484 static int openAddPayloadApp(
3485 lua_State *L
3486 )
3487 {
3488 unsigned int payloadAppId;
3489 Detector *detector;
3490 DetectorUserData *detectorUserData = checkDetectorUserData(L, 1);
3491
3492 payloadAppId = lua_tonumber(L, 2);
3493
3494 /*check inputs and whether this function is called in context of a */
3495 /*packet */
3496 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
3497 {
3498 lua_pushnumber(L, -1);
3499 return 1;
3500 }
3501
3502 detector = detectorUserData->pDetector;
3503
3504 if (!detector->client.appModule.api)
3505 {
3506 lua_pushnumber(L, -1);
3507 return 1;
3508 }
3509
3510 detector->client.appModule.api->add_payload(detector->validateParams.flowp, payloadAppId);
3511
3512 lua_pushnumber(L, 0);
3513 return 1;
3514 }
3515
3516 int openAddHttpPattern(lua_State *L)
3517 {
3518 int index = 1;
3519 tAppIdConfig *pConfig;
3520
3521 /* Verify detector user data and that we are not in packet context */
3522 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
3523 if (!detectorUserData)
3524 {
3525 _dpd.errMsg( "Invalid HTTP detector user data addHttpPattern.");
3526 return 0;
3527 }
3528
3529 pConfig = detectorUserData->pDetector->pAppidNewConfig;
3530
3531 /* Verify valid pattern type */
3532 enum httpPatternType pType = (enum httpPatternType) lua_tointeger(L, index++);
3533 if(pType < HTTP_PAYLOAD || pType > HTTP_URL)
3534 {
3535 _dpd.errMsg( "Invalid HTTP pattern type.");
3536 return 0;
3537 }
3538
3539 /* Verify valid DHSequence */
3540 DHPSequence seq = (DHPSequence) lua_tointeger(L, index++);
3541 if(seq < SINGLE || seq > USER_AGENT_HEADER)
3542 {
3543 _dpd.errMsg( "Invalid HTTP DHP Sequence.");
3544 return 0;
3545 }
3546
3547 uint32_t serviceAppId = lua_tointeger(L, index++);
3548 uint32_t clientAppId = lua_tointeger(L, index++);
3549 uint32_t payloadAppId = lua_tointeger(L, index++);
3550
3551 if (detectorUserData->pDetector->validateParams.pkt)
3552 {
3553 _dpd.errMsg("Invalid detector context addHttpPattern: serviceAppId %u; clientAppId %u; payloadAppId %u\n",serviceAppId, clientAppId, payloadAppId);
3554 return 0;
3555 }
3556
3557 /* Verify that pattern is a valid string */
3558 size_t pattern_size = 0;
3559 uint8_t* pattern_str = (uint8_t*) strdup(lua_tolstring(L, index++, &pattern_size));
3560 if(pattern_str == NULL || pattern_size == 0)
3561 {
3562 _dpd.errMsg( "Invalid HTTP pattern string.");
3563 free(pattern_str);
3564 return 0;
3565 }
3566
3567 HTTPListElement *element = calloc(1, sizeof(*element));
3568 if (element == NULL)
3569 {
3570 _dpd.errMsg( "Failed to allocate HTTP list element memory.");
3571 free(pattern_str);
3572 return 0;
3573 }
3574
3575 DetectorHTTPPattern *pattern = &element->detectorHTTPPattern;
3576 pattern->seq = seq;
3577 pattern->service_id = serviceAppId;
3578 pattern->client_app = clientAppId;
3579 pattern->payload = payloadAppId;
3580 pattern->pattern = pattern_str;
3581 pattern->pattern_size = (int) pattern_size;
3582 pattern->appId = APP_ID_NONE;
3583
3584 switch(pType)
3585 {
3586 case HTTP_PAYLOAD:
3587 element->next = pConfig->httpPatternLists.hostPayloadPatternList;
3588 pConfig->httpPatternLists.hostPayloadPatternList = element;
3589 break;
3590
3591 case HTTP_URL:
3592 element->next = pConfig->httpPatternLists.urlPatternList;
3593 pConfig->httpPatternLists.urlPatternList = element;
3594 break;
3595
3596 case HTTP_USER_AGENT:
3597 element->next = pConfig->httpPatternLists.clientAgentPatternList;
3598 pConfig->httpPatternLists.clientAgentPatternList = element;
3599 break;
3600 }
3601
3602 appInfoSetActive(serviceAppId, true);
3603 appInfoSetActive(clientAppId, true);
3604 appInfoSetActive(payloadAppId, true);
3605
3606 return 0;
3607 }
3608
3609 static int openAddUrlPattern(lua_State *L)
3610 {
3611 int index = 1;
3612 DetectorAppUrlPattern **tmp;
3613 const char *tmpString;
3614
3615 /* Verify detector user data and that we are not in packet context */
3616 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
3617 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
3618 {
3619 _dpd.errMsg( "Invalid HTTP detector user data in addAppUrl.");
3620 return 0;
3621 }
3622
3623 tAppIdConfig *pConfig = detectorUserData->pDetector->pAppidNewConfig;
3624 u_int32_t service_id = lua_tointeger(L, index++);
3625 u_int32_t client_id = lua_tointeger(L, index++);
3626 u_int32_t payload_id = lua_tointeger(L, index++);
3627
3628 if (detectorUserData->pDetector->validateParams.pkt)
3629 {
3630 _dpd.errMsg("Invalid HTTP detector context addAppUrl: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
3631 return 0;
3632 }
3633
3634 /* Verify that host pattern is a valid string */
3635 size_t hostPatternSize = 0;
3636 u_int8_t* hostPattern = NULL;
3637 tmpString = lua_tolstring(L, index++, &hostPatternSize);
3638 if(!tmpString || !hostPatternSize)
3639 {
3640 _dpd.errMsg( "Invalid host pattern string: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
3641 return 0;
3642 }
3643 else if (!(hostPattern = (u_int8_t *)strdup(tmpString)))
3644 {
3645 _dpd.errMsg( "Failed to duplicate host pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
3646 return 0;
3647 }
3648
3649 /* Verify that path pattern is a valid string */
3650 size_t pathPatternSize = 0;
3651 u_int8_t* pathPattern = NULL;
3652 tmpString = lua_tolstring(L, index++, &pathPatternSize);
3653 if(!tmpString || !pathPatternSize)
3654 {
3655 _dpd.errMsg( "Invalid path pattern string: service_id %u; client_id %u; payload %u\n.",service_id, client_id, payload_id);
3656 free(hostPattern);
3657 return 0;
3658 }
3659 else if (!(pathPattern = (u_int8_t *)strdup(tmpString)))
3660 {
3661 _dpd.errMsg( "Failed to duplicate path pattern: %s, service_id %u; client_id %u; payload %u\n.",tmpString, service_id, client_id, payload_id);
3662 free(hostPattern);
3663 return 0;
3664 }
3665
3666 /* Verify that scheme pattern is a valid string */
3667 size_t schemePatternSize;
3668 u_int8_t* schemePattern = NULL;
3669 tmpString = lua_tolstring(L, index++, &schemePatternSize);
3670 if(!tmpString || !schemePatternSize)
3671 {
3672 _dpd.errMsg( "Invalid scheme pattern string: service_id %u; client_id %u; payload_id %u\n",service_id, client_id, payload_id);
3673 free(pathPattern);
3674 free(hostPattern);
3675 return 0;
3676 }
3677 else if (!(schemePattern = (u_int8_t*) strdup(tmpString)))
3678 {
3679 _dpd.errMsg( "Failed to duplicate scheme pattern: %s, service_id %u; client_id %u; payload_id %u\n.",tmpString, service_id, client_id, payload_id);
3680 free(pathPattern);
3681 free(hostPattern);
3682 return 0;
3683 }
3684
3685 /* Allocate memory for data structures */
3686 DetectorAppUrlPattern *pattern = malloc(sizeof(DetectorAppUrlPattern));
3687 if (!pattern)
3688 {
3689 _dpd.errMsg( "Failed to allocate HTTP pattern memory.");
3690 free(hostPattern);
3691 free(pathPattern);
3692 free(schemePattern);
3693 return 0;
3694 }
3695
3696
3697 pattern->userData.service_id = service_id;
3698 pattern->userData.client_app = client_id;
3699 pattern->userData.payload = payload_id;
3700 pattern->userData.appId = APP_ID_NONE;
3701 pattern->userData.query.pattern = NULL;
3702 pattern->userData.query.patternSize = 0;
3703 pattern->patterns.host.pattern = hostPattern;
3704 pattern->patterns.host.patternSize = (int) hostPatternSize;
3705 pattern->patterns.path.pattern = pathPattern;
3706 pattern->patterns.path.patternSize = (int) pathPatternSize;
3707 pattern->patterns.scheme.pattern = schemePattern;
3708 pattern->patterns.scheme.patternSize = (int) schemePatternSize;
3709
3710 DetectorAppUrlList *urlList = &pConfig->httpPatternLists.appUrlList;
3711
3712 /**first time usedCount and allocatedCount are both 0, urlPattern will be NULL.
3713 * This case is same as malloc. In case of error, realloc will return NULL, and
3714 * original urlPattern buffer is left untouched.
3715 */
3716 if (urlList->usedCount == urlList->allocatedCount)
3717 {
3718 tmp = realloc(urlList->urlPattern, (urlList->allocatedCount+URL_LIST_STEP_SIZE)*sizeof(*tmp));
3719 if (!tmp)
3720 {
3721 FreeDetectorAppUrlPattern(pattern);
3722 return 0;
3723 }
3724 urlList->urlPattern = tmp;
3725 urlList->allocatedCount += URL_LIST_STEP_SIZE;
3726 }
3727
3728 urlList->urlPattern[urlList->usedCount++] = pattern;
3729
3730 appInfoSetActive(service_id, true);
3731 appInfoSetActive(client_id, true);
3732 appInfoSetActive(payload_id, true);
3733
3734 return 0;
3735 }
3736
3737 void CleanClientPortPatternList(tAppIdConfig *pConfig)
3738 {
3739 tPortPatternNode *tmp;
3740
3741 if ( pConfig->clientPortPattern)
3742 {
3743 while ((tmp = pConfig->clientPortPattern->luaInjectedPatterns))
3744 {
3745 pConfig->clientPortPattern->luaInjectedPatterns = tmp->next;
3746 free(tmp->pattern);
3747 free(tmp->detectorName);
3748 free(tmp);
3749 }
3750
3751 free(pConfig->clientPortPattern);
3752 }
3753 }
3754
3755 void CleanServicePortPatternList(tAppIdConfig *pConfig)
3756 {
3757 tPortPatternNode *tmp;
3758
3759 if ( pConfig->servicePortPattern)
3760 {
3761 while ((tmp = pConfig->servicePortPattern->luaInjectedPatterns))
3762 {
3763 pConfig->servicePortPattern->luaInjectedPatterns = tmp->next;
3764 free(tmp->pattern);
3765 free(tmp->detectorName);
3766 free(tmp);
3767 }
3768
3769 free(pConfig->servicePortPattern);
3770 }
3771 }
3772
3773 /* Add a port and pattern based detection for client application. Both port and pattern criteria
3774 * must be met before client application is deemed detected.
3775 *
3776 * @param lua_State* - Lua state variable.
3777 * @param proto/stack - Protocol (IPPROTO_TCP/DC.ipproto.tcp (6) or
3778 * IPPROTO_UDP/DC.ipproto.udp (17)).
3779 * @param port/stack - port number to register.
3780 * @param pattern/stack - pattern to be matched.
3781 * @param patternLenght/stack - length of pattern
3782 * @param offset/stack - offset into packet payload where matching should start.
3783 * @param appId/stack - App ID to use for this detector.
3784 * @return int - Number of elements on stack, which is always 0.
3785 */
3786 static int addPortPatternClient(lua_State *L)
3787 {
3788 int index = 1;
3789 tAppIdConfig *pConfig;
3790 tPortPatternNode *pPattern;
3791 uint8_t protocol;
3792 uint16_t port;
3793 const char*pattern;
3794 size_t patternSize = 0;
3795 unsigned position;
3796 tAppId appId;
3797
3798 /* Verify detector user data and that we are not in packet context */
3799 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
3800 if (!detectorUserData)
3801 {
3802 _dpd.errMsg( "addPortPatternClient(): Invalid detector user data");
3803 return 0;
3804 }
3805
3806 pConfig = detectorUserData->pDetector->pAppidNewConfig;
3807 protocol = lua_tonumber(L, index++);
3808 //port = lua_tonumber(L, index++);
3809 port = 0;
3810 pattern = lua_tolstring(L, index++, &patternSize);
3811 position = lua_tonumber(L, index++);
3812 appId = lua_tointeger(L, index++);
3813
3814 if (!pConfig->clientPortPattern)
3815 {
3816 if (!(pConfig->clientPortPattern = calloc(1, sizeof(*pConfig->clientPortPattern))))
3817 {
3818 _dpd.errMsg( "addPortPatternClient(): memory allocation failure");
3819 return 0;
3820 }
3821 }
3822 if (appId <= APP_ID_NONE || !pattern || !patternSize || (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP))
3823 {
3824 _dpd.errMsg("addPortPatternClient(): Invalid input in %s\n", detectorUserData->pDetector->name);
3825 return 0;
3826 }
3827 if (!(pPattern = calloc(1, sizeof(*pPattern))))
3828 {
3829 _dpd.errMsg( "addPortPatternClient(): memory allocation failure");
3830 return 0;
3831 }
3832 if (!(pPattern->pattern = malloc(patternSize)))
3833 {
3834 _dpd.errMsg( "addPortPatternClient(): memory allocation failure");
3835 free(pPattern);
3836 return 0;
3837 }
3838
3839 pPattern->appId = appId;
3840 pPattern->protocol = protocol;
3841 pPattern->port = port;
3842 memcpy(pPattern->pattern, pattern, patternSize);
3843 pPattern->length = patternSize;
3844 pPattern->offset = position;
3845 if (!(pPattern->detectorName = strdup(detectorUserData->pDetector->name)))
3846 {
3847 _dpd.errMsg( "addPortPatternClient(): memory allocation failure");
3848 free(pPattern->pattern);
3849 free(pPattern);
3850 return 0;
3851 }
3852
3853 //insert ports in order.
3854 {
3855 tPortPatternNode **prev;
3856 tPortPatternNode **curr;
3857
3858 prev = NULL;
3859 for (curr = &pConfig->clientPortPattern->luaInjectedPatterns;
3860 *curr;
3861 prev = curr, curr = &((*curr)->next))
3862 {
3863 if (strcmp(pPattern->detectorName, (*curr)->detectorName) || pPattern->protocol < (*curr)->protocol
3864 || pPattern->port < (*curr)->port)
3865 break;
3866 }
3867 if (prev)
3868 {
3869 pPattern->next = (*prev)->next;
3870 (*prev)->next = pPattern;
3871 }
3872 else
3873 {
3874 pPattern->next = *curr;
3875 *curr = pPattern;
3876 }
3877 }
3878
3879 appInfoSetActive(appId, true);
3880
3881 return 0;
3882 }
3883
3884 /* Add a port and pattern based detection for service application. Both port and pattern criteria
3885 * must be met before service application is deemed detected.
3886 *
3887 * @param lua_State* - Lua state variable.
3888 * @param proto/stack - Protocol (IPPROTO_TCP/DC.ipproto.tcp (6) or
3889 * IPPROTO_UDP/DC.ipproto.udp (17)).
3890 * @param port/stack - port number to register.
3891 * @param pattern/stack - pattern to be matched.
3892 * @param patternLenght/stack - length of pattern
3893 * @param offset/stack - offset into packet payload where matching should start.
3894 * @param appId/stack - App ID to use for this detector.
3895 * @return int - Number of elements on stack, which is always 0.
3896 */
3897 static int addPortPatternService(lua_State *L)
3898 {
3899 int index = 1;
3900 size_t patternSize = 0;
3901 tAppIdConfig *pConfig;
3902 tPortPatternNode *pPattern;
3903 uint8_t protocol;
3904 uint16_t port;
3905 const char *pattern;
3906 unsigned position;
3907 tAppId appId;
3908
3909 /* Verify detector user data and that we are not in packet context */
3910 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
3911 if (!detectorUserData)
3912 {
3913 _dpd.errMsg( "addPortPatternService(): Invalid detector user data");
3914 return 0;
3915 }
3916
3917 pConfig = detectorUserData->pDetector->pAppidNewConfig;
3918 protocol = lua_tonumber(L, index++);
3919 port = lua_tonumber(L, index++);
3920 pattern = lua_tolstring(L, index++, &patternSize);
3921 position = lua_tonumber(L, index++);
3922 appId = lua_tointeger(L, index++);
3923
3924 if (!pConfig->servicePortPattern)
3925 {
3926 if (!(pConfig->servicePortPattern = calloc(1, sizeof(*pConfig->servicePortPattern))))
3927 {
3928 _dpd.errMsg( "addPortPatternService(): memory allocation failure");
3929 return 0;
3930 }
3931 }
3932 if (!(pPattern = calloc(1, sizeof(*pPattern))))
3933 {
3934 _dpd.errMsg( "addPortPatternService(): memory allocation failure");
3935 return 0;
3936 }
3937 if (!(pPattern->pattern = malloc(patternSize)))
3938 {
3939 _dpd.errMsg( "addPortPatternService(): memory allocation failure");
3940 free(pPattern);
3941 return 0;
3942 }
3943
3944 pPattern->appId = appId;
3945 pPattern->protocol = protocol;
3946 pPattern->port = port;
3947 memcpy(pPattern->pattern, pattern, patternSize);
3948 pPattern->length = patternSize;
3949 pPattern->offset = position;
3950 if (!(pPattern->detectorName = strdup(detectorUserData->pDetector->name)))
3951 {
3952 _dpd.errMsg( "addPortPatternService(): memory allocation failure");
3953 free(pPattern->pattern);
3954 free(pPattern);
3955 return 0;
3956 }
3957
3958 //insert ports in order.
3959 {
3960 tPortPatternNode **prev;
3961 tPortPatternNode **curr;
3962
3963 prev = NULL;
3964 for (curr = &pConfig->servicePortPattern->luaInjectedPatterns;
3965 *curr;
3966 prev = curr, curr = &((*curr)->next))
3967 {
3968 if (strcmp(pPattern->detectorName, (*curr)->detectorName) || pPattern->protocol < (*curr)->protocol
3969 || pPattern->port < (*curr)->port)
3970 break;
3971 }
3972 if (prev)
3973 {
3974 pPattern->next = (*prev)->next;
3975 (*prev)->next = pPattern;
3976 }
3977 else
3978 {
3979 pPattern->next = *curr;
3980 *curr = pPattern;
3981 }
3982 }
3983
3984 appInfoSetActive(appId, true);
3985
3986 return 0;
3987 }
3988
3989
3990 /*Lua should inject patterns in <clientAppId, clientVersion, multi-Pattern> format. */
3991 static int Detector_addSipServer(lua_State *L)
3992 {
3993 int index = 1;
3994
3995 /* Verify detector user data and that we are not in packet context */
3996 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
3997 if (!detectorUserData)
3998 {
3999 _dpd.errMsg( "Invalid HTTP detector user data addSipServer.");
4000 return 0;
4001 }
4002
4003 u_int32_t client_app = lua_tointeger(L, index++);
4004 const char *clientVersion = lua_tostring(L, index++);
4005 if(!clientVersion )
4006 {
4007 _dpd.errMsg( "Invalid sip client version string.");
4008 return 0;
4009 }
4010
4011 if (detectorUserData->pDetector->validateParams.pkt)
4012 {
4013 _dpd.errMsg("Invalid detector context addSipServer: client_app %u\n",client_app);
4014 return 0;
4015 }
4016
4017 /* Verify that ua pattern is a valid string */
4018 const char* uaPattern = lua_tostring(L, index++);
4019 if(!uaPattern)
4020 {
4021 _dpd.errMsg( "Invalid sip ua pattern string.");
4022 return 0;
4023 }
4024
4025 sipServerPatternAdd(client_app, clientVersion, uaPattern, &detectorUserData->pDetector->pAppidNewConfig->detectorSipConfig);
4026
4027 appInfoSetActive(client_app, true);
4028
4029 return 0;
4030 }
4031
4032 static inline int ConvertStringToAddress(const char * string, sfaddr_t * address)
4033 {
4034 int af;
4035 struct in6_addr buf;
4036
4037 if (strchr(string, ':'))
4038 af = AF_INET6;
4039 else if (strchr(string, '.'))
4040 af = AF_INET;
4041 else
4042 return 0;
4043
4044 if (inet_pton(af, string, &buf))
4045 {
4046 if (sfip_set_raw(address, &buf, af) != SFIP_SUCCESS)
4047 return 0;
4048 }
4049 else
4050 return 0;
4051
4052 return 1; // success
4053 }
4054
4055 /**Creates a future flow based on the current flow. When the future flow is
4056 * seen, the app ID will simply be declared with the info given here.
4057 *
4058 * @param Lua_State* - Lua state variable.
4059 * @param detector/stack - detector object.
4060 * @param client_addr/stack - client address of the future flow
4061 * @param client_port/stack - client port of the the future flow (can use 0 for wildcard here)
4062 * @param server_addr/stack - server address of the future flow
4063 * @param server_port/stack - server port of the future flow
4064 * @param proto/stack - protocol type (see define IPPROTO_xxxx in /usr/include/netinet/in.h)
4065 * @param service_app_id/stack - service app ID to declare for future flow (can be 0 for none)
4066 * @param client_app_id/stack - client app ID to declare for future flow (can be 0 for none)
4067 * @param payload_app_id/stack - payload app ID to declare for future flow (can be 0 for none)
4068 * @param app_id_to_snort/stack - AppID's app ID entry to convert to Snort app ID (see note below)
4069 * @return int - number of elements on stack, which is 1 if successful, 0 otherwise.
4070 *
4071 * Notes: For app_id_to_snort, use the app ID that AppID knows about (it'll
4072 * probably be a repeat of one of the other 3 app IDs given here). For
4073 * example, for "FTP Data", use 166. Internally, this'll be converted to the
4074 * app ID that Snort recognizes ("ftp-data"). For this to really mean
4075 * anything, the app IDs entry in appMapping.data should have a Snort app ID
4076 * defined.
4077 *
4078 * Example: createFutureFlow("192.168.0.200", 0, "192.168.0.100", 20, 6, 166, 0, 0, 166)
4079 */
4080 static int createFutureFlow (lua_State *L)
4081 {
4082 sfaddr_t client_addr;
4083 sfaddr_t server_addr;
4084 uint8_t proto;
4085 uint16_t client_port, server_port;
4086 DetectorUserData *detectorUserData = NULL;
4087 char *pattern;
4088 tAppId service_app_id, client_app_id, payload_app_id, app_id_to_snort;
4089 int16_t snort_app_id;
4090 tAppIdData *fp;
4091
4092 detectorUserData = checkDetectorUserData(L, 1);
4093
4094 /*check inputs and whether this function is called in context of a packet */
4095 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
4096 {
4097 return 0;
4098 }
4099
4100 pattern = (char *)lua_tostring(L, 2);
4101 if (!ConvertStringToAddress(pattern, &client_addr))
4102 return 0;
4103
4104 client_port = lua_tonumber(L, 3);
4105
4106 pattern = (char *)lua_tostring(L, 4);
4107 if (!ConvertStringToAddress(pattern, &server_addr))
4108 return 0;
4109
4110 server_port = lua_tonumber(L, 5);
4111
4112 proto = lua_tonumber(L, 6);
4113
4114 service_app_id = lua_tointeger(L, 7);
4115 client_app_id = lua_tointeger(L, 8);
4116 payload_app_id = lua_tointeger(L, 9);
4117
4118 app_id_to_snort = lua_tointeger(L, 10);
4119 if (app_id_to_snort > APP_ID_NONE)
4120 {
4121 AppInfoTableEntry* entry = appInfoEntryGet(app_id_to_snort, appIdActiveConfigGet());
4122 if (NULL == entry)
4123 return 0;
4124 snort_app_id = entry->snortId;
4125 }
4126 else
4127 {
4128 snort_app_id = 0;
4129 }
4130
4131 fp = AppIdEarlySessionCreate(detectorUserData->pDetector->validateParams.flowp,
4132 detectorUserData->pDetector->validateParams.pkt,
4133 &client_addr, client_port, &server_addr, server_port, proto,
4134 snort_app_id,
4135 APPID_EARLY_SESSION_FLAG_FW_RULE);
4136 if (fp)
4137 {
4138 fp->serviceAppId = service_app_id;
4139 fp->clientAppId = client_app_id;
4140 fp->payloadAppId = payload_app_id;
4141 setAppIdFlag(fp, APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_NOT_A_SERVICE | APPID_SESSION_PORT_SERVICE_DONE);
4142 fp->rnaServiceState = RNA_STATE_FINISHED;
4143 fp->rnaClientState = RNA_STATE_FINISHED;
4144
4145 return 1;
4146 }
4147 else
4148 return 0;
4149 }
4150
4151 static int isMidStreamSession(lua_State *L)
4152 {
4153 DetectorUserData *detectorUserData = NULL;
4154
4155 detectorUserData = checkDetectorUserData(L, 1);
4156
4157 /*check inputs and whether this function is called in context of a packet */
4158 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
4159 {
4160 lua_pushnumber(L, -1);
4161 return -1;
4162 }
4163
4164 if (_dpd.sessionAPI->get_session_flags(detectorUserData->pDetector->validateParams.pkt->stream_session) & SSNFLAG_MIDSTREAM)
4165 {
4166 lua_pushnumber(L, 1);
4167 return 1;
4168 }
4169
4170 lua_pushnumber(L, 0);
4171 return 0;
4172 }
4173
4174 /* Check if traffic is going through an HTTP proxy */
4175 static int isHttpTunnel(lua_State *L)
4176 {
4177 DetectorUserData *detectorUserData = NULL;
4178
4179 detectorUserData = checkDetectorUserData(L, 1);
4180
4181 /*check inputs and whether this function is called in context of a packet */
4182 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
4183 return -1;
4184
4185 httpSession *hsession = detectorUserData->pDetector->validateParams.flowp->hsession;
4186 if (hsession)
4187 {
4188 tunnelDest *tunDest = hsession->tunDest;
4189 if (tunDest)
4190 {
4191 lua_pushboolean(L, 1);
4192 return 1;
4193 }
4194 }
4195
4196 lua_pushboolean(L, 0);
4197 return 0;
4198 }
4199
4200 /* Get destination IP tunneled through a proxy */
4201 static int getHttpTunneledIp(lua_State* L)
4202 {
4203 DetectorUserData *detectorUserData = NULL;
4204
4205 detectorUserData = checkDetectorUserData(L, 1);
4206
4207 /*check inputs and whether this function is called in context of a packet */
4208 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
4209 return -1;
4210
4211 httpSession *hsession = detectorUserData->pDetector->validateParams.flowp->hsession;
4212 if (hsession)
4213 {
4214 tunnelDest *tunDest = hsession->tunDest;
4215 if (!tunDest)
4216 lua_pushnumber(L, 0);
4217 else
4218 lua_pushnumber(L, sfaddr_get_ip4_value(&(tunDest->ip)));
4219 }
4220
4221 return 1;
4222 }
4223
4224 /* Get port tunneled through a proxy */
4225 static int getHttpTunneledPort(lua_State* L)
4226 {
4227 DetectorUserData *detectorUserData = NULL;
4228
4229 detectorUserData = checkDetectorUserData(L, 1);
4230
4231 /*check inputs and whether this function is called in context of a packet */
4232 if (!detectorUserData || !detectorUserData->pDetector->validateParams.pkt)
4233 return -1;
4234
4235 httpSession *hsession = detectorUserData->pDetector->validateParams.flowp->hsession;
4236 if (hsession)
4237 {
4238 tunnelDest *tunDest = hsession->tunDest;
4239 if (!tunDest)
4240 lua_pushnumber(L, 0);
4241 else
4242 lua_pushnumber(L, tunDest->port);
4243 }
4244
4245 return 1;
4246 }
4247
4248 /*Lua should inject patterns in <clientAppId, classId> format. */
4249 static int Detector_addCipConnectionClass(lua_State *L)
4250 {
4251 int index = 1;
4252
4253 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
4254 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
4255 {
4256 _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
4257 return -1;
4258 }
4259
4260 uint32_t appId = lua_tointeger(L, index++);
4261 uint32_t classId = lua_tointeger(L, index++);
4262
4263 if (CipAddConnectionClass(appId, classId) == -1)
4264 {
4265 return -1;
4266 }
4267
4268 appInfoSetActive(appId, true);
4269
4270 return 0;
4271 }
4272
4273 /*Lua should inject patterns in <clientAppId, classId, serviceId> format. */
4274 static int Detector_addCipPath(lua_State *L)
4275 {
4276 int index = 1;
4277
4278 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
4279 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
4280 {
4281 _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
4282 return -1;
4283 }
4284
4285 uint32_t appId = lua_tointeger(L, index++);
4286 uint32_t classId = lua_tointeger(L, index++);
4287 uint8_t serviceId = lua_tointeger(L, index++);
4288
4289 if (CipAddPath(appId, classId, serviceId) == -1)
4290 {
4291 return -1;
4292 }
4293
4294 appInfoSetActive(appId, true);
4295
4296 return 0;
4297 }
4298
4299 /*Lua should inject patterns in <clientAppId, classId, isClassInstance, attributeId> format. */
4300 static int Detector_addCipSetAttribute(lua_State *L)
4301 {
4302 int index = 1;
4303
4304 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
4305 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
4306 {
4307 _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
4308 return -1;
4309 }
4310
4311 uint32_t appId = lua_tointeger(L, index++);
4312 uint32_t classId = lua_tointeger(L, index++);
4313 bool isClassInstance = lua_toboolean(L, index++);
4314 uint32_t attributeId = lua_tointeger(L, index++);
4315
4316 if (CipAddSetAttribute(appId, classId, isClassInstance, attributeId) == -1)
4317 {
4318 return -1;
4319 }
4320
4321 appInfoSetActive(appId, true);
4322
4323 return 0;
4324 }
4325
4326
4327 /*Lua should inject patterns in <clientAppId, serviceId> format. */
4328 static int Detector_addCipExtendedSymbolService(lua_State *L)
4329 {
4330 int index = 1;
4331
4332 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
4333 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
4334 {
4335 _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
4336 return -1;
4337 }
4338
4339 uint32_t appId = lua_tointeger(L, index++);
4340 uint8_t serviceId = lua_tointeger(L, index++);
4341
4342 if (CipAddExtendedSymbolService(appId, serviceId) == -1)
4343 {
4344 return -1;
4345 }
4346
4347 appInfoSetActive(appId, true);
4348
4349 return 0;
4350 }
4351
4352 /*Lua should inject patterns in <clientAppId, serviceId> format. */
4353 static int Detector_addCipService(lua_State *L)
4354 {
4355 int index = 1;
4356
4357 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
4358 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
4359 {
4360 _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
4361 return -1;
4362 }
4363
4364 uint32_t appId = lua_tointeger(L, index++);
4365 uint16_t serviceId = lua_tointeger(L, index++);
4366
4367 if (CipAddService(appId, serviceId) == -1)
4368 {
4369 return -1;
4370 }
4371
4372 appInfoSetActive(appId, true);
4373
4374 return 0;
4375 }
4376
4377 /*Lua should inject patterns in <clientAppId, enipCommandId> format. */
4378 static int Detector_addEnipCommand(lua_State *L)
4379 {
4380 int index = 1;
4381
4382 DetectorUserData *detectorUserData = checkDetectorUserData(L, index++);
4383 if (!detectorUserData || detectorUserData->pDetector->validateParams.pkt)
4384 {
4385 _dpd.errMsg("%s: Invalid detector user data or context.\n", __func__);
4386 return -1;
4387 }
4388
4389 uint32_t appId = lua_tointeger(L, index++);
4390 uint16_t commandId = lua_tointeger(L, index++);
4391
4392 if (CipAddEnipCommand(appId, commandId) == -1)
4393 {
4394 return -1;
4395 }
4396
4397 appInfoSetActive(appId, true);
4398
4399 return 0;
4400 }
4401
4402 static const luaL_Reg Detector_methods[] = {
4403 /* Obsolete API names. No longer use these! They are here for backward
4404 * compatibility and will eventually be removed. */
4405 /* - "memcmp" is now "matchSimplePattern" (below) */
4406 {"memcmp", Detector_memcmp},
4407 /* - "getProtocolType" is now "getL4Protocol" (below) */
4408 {"getProtocolType", Detector_getProtocolType},
4409 /* - "inCompatibleData" is now "markIncompleteData" (below) */
4410 {"inCompatibleData", service_inCompatibleData},
4411 /* - "addDataId" is now "addAppIdDataToFlow" (below) */
4412 {"addDataId", service_addDataId},
4413 /* - "service_inCompatibleData" is now "service_markIncompleteData" (below) */
4414 {"service_inCompatibleData", service_inCompatibleData},
4415 /* - "service_addDataId" is now "service_addAppIdDataToFlow" (below) */
4416 {"service_addDataId", service_addDataId},
4417
4418 {"getPacketSize", Detector_getPacketSize},
4419 {"getPacketDir", Detector_getPacketDir},
4420 {"matchSimplePattern", Detector_memcmp},
4421 {"getPcreGroups", Detector_getPcreGroups},
4422 {"getL4Protocol", Detector_getProtocolType},
4423 {"getPktSrcAddr", Detector_getPktSrcIPAddr},
4424 {"getPktDstAddr", Detector_getPktDstIPAddr},
4425 {"getPktSrcPort", Detector_getPktSrcPort},
4426 {"getPktDstPort", Detector_getPktDstPort},
4427 {"getPktCount", Detector_getPktCount},
4428 {"getFlow", Detector_getFlow},
4429 {"htons", Detector_htons},
4430 {"htonl", Detector_htonl},
4431 {"log", Detector_logMessage},
4432 {"addHttpPattern", Detector_addHttpPattern},
4433 {"addAppUrl", Detector_addAppUrl},
4434 {"addRTMPUrl", Detector_addRTMPUrl},
4435 {"addContentTypePattern", Detector_addContentTypePattern},
4436 {"addSSLCertPattern", Detector_addSSLCertPattern},
4437 {"addSipUserAgent", Detector_addSipUserAgent},
4438 {"addSipServer", Detector_addSipServer},
4439 {"addSSLCnamePattern", Detector_addSSLCnamePattern},
4440 {"addHostPortApp", Detector_addHostPortApp},
4441 {"addHostPortAppDynamic", Detector_addHostPortAppDynamic},
4442 {"addDNSHostPattern", Detector_addDNSHostPattern},
4443 {"registerClientDetectorCallback", Detector_registerClientCallback},
4444 {"registerServiceDetectorCallback", Detector_registerServiceCallback},
4445
4446 /* CIP registration */
4447 {"addCipConnectionClass", Detector_addCipConnectionClass},
4448 {"addCipPath", Detector_addCipPath},
4449 {"addCipSetAttribute", Detector_addCipSetAttribute},
4450 {"addCipExtendedSymbolService", Detector_addCipExtendedSymbolService},
4451 {"addCipService", Detector_addCipService},
4452 {"addEnipCommand", Detector_addEnipCommand},
4453
4454 /*Obsolete - new detectors should not use this API */
4455 {"init", service_init},
4456 {"registerPattern", service_registerPattern},
4457 {"getServiceID", service_getServiceId},
4458 {"addPort", service_addPorts},
4459 {"removePort", service_removePorts},
4460 {"setServiceName", service_setServiceName},
4461 {"getServiceName", service_getServiceName},
4462 {"isCustomDetector", service_isCustomDetector},
4463 {"setValidator", service_setValidator},
4464 {"addService", service_addService},
4465 {"failService", service_failService},
4466 {"inProcessService", service_inProcessService},
4467 {"markIncompleteData", service_inCompatibleData},
4468 {"analyzePayload", service_analyzePayload},
4469 {"addAppIdDataToFlow", service_addDataId},
4470
4471 /*service API */
4472 {"service_init", service_init},
4473 {"service_registerPattern", service_registerPattern},
4474 {"service_getServiceId", service_getServiceId},
4475 {"service_addPort", service_addPorts},
4476 {"service_removePort", service_removePorts},
4477 {"service_setServiceName", service_setServiceName},
4478 {"service_getServiceName", service_getServiceName},
4479 {"service_isCustomDetector", service_isCustomDetector},
4480 {"service_setValidator", service_setValidator},
4481 {"service_addService", service_addService},
4482 {"service_failService", service_failService},
4483 {"service_inProcessService", service_inProcessService},
4484 {"service_markIncompleteData", service_inCompatibleData},
4485 {"service_analyzePayload", service_analyzePayload},
4486 {"service_addAppIdDataToFlow", service_addDataId},
4487 {"service_addClient", service_addClient},
4488
4489 /*client init API */
4490 {"client_init", client_init},
4491 {"client_registerPattern", client_registerPattern},
4492 {"client_getServiceId", service_getServiceId},
4493
4494 /*client service API */
4495 {"client_addApp", client_addApp},
4496 {"client_addInfo", client_addInfo},
4497 {"client_addUser", client_addUser},
4498 {"client_addPayload", client_addPayload},
4499
4500 //HTTP Multi Pattern engine
4501 {"CHPCreateApp", Detector_CHPCreateApp},
4502 {"CHPAddAction", Detector_CHPAddAction},
4503 {"CHPMultiCreateApp", Detector_CHPMultiCreateApp}, // allows multiple detectors, same appId
4504 {"CHPMultiAddAction", Detector_CHPMultiAddAction},
4505
4506 //App Forecasting engine
4507 {"AFAddApp", Detector_AFAddApp},
4508
4509 {"portOnlyService", Detector_portOnlyService},
4510
4511 /* Length-based detectors. */
4512 {"AddLengthBasedDetector", Detector_lengthAppCacheAdd},
4513
4514 {"registerAppId" , common_registerAppId},
4515
4516 {"open_createApp", openCreateApp},
4517 {"open_addClientApp", openAddClientApp},
4518 {"open_addServiceApp", openAddServiceApp},
4519 {"open_addPayloadApp", openAddPayloadApp},
4520 {"open_addHttpPattern", openAddHttpPattern},
4521 {"open_addUrlPattern", openAddUrlPattern},
4522
4523 {"addPortPatternClient", addPortPatternClient},
4524 {"addPortPatternService", addPortPatternService},
4525
4526 {"createFutureFlow", createFutureFlow},
4527 {"isMidStreamSession", isMidStreamSession},
4528
4529 { "isHttpTunnel", isHttpTunnel },
4530 { "getHttpTunneledIp", getHttpTunneledIp },
4531 { "getHttpTunneledPort", getHttpTunneledPort },
4532
4533 {0, 0}
4534 };
4535
4536 /**This function performs a clean exit on an api instance. It is called when RNA is performing
4537 * a clean exit.
4538 */
4539 void Detector_fini(void *data)
4540 {
4541 lua_State *myLuaState;
4542 Detector *detector = (Detector*) data;
4543
4544 #ifdef LUA_DETECTOR_DEBUG
4545 _dpd.debugMsg(DEBUG_LOG,"Finishing detector %s\n",detector->server.serviceModule.name);
4546 #endif
4547
4548 myLuaState = detector->myLuaState;
4549
4550 if (detector->packageInfo.server.cleanFunctionName && lua_checkstack(myLuaState, 1))
4551 {
4552 lua_getglobal(myLuaState, detector->packageInfo.server.cleanFunctionName);
4553
4554 if (lua_pcall(myLuaState, 0, 0, 0 ))
4555 {
4556 /*See comment at first lua_pcall() */
4557 #ifdef LUA_DETECTOR_DEBUG
4558 _dpd.errMsg( "%s: error running %s in lua: %s", detector->server.serviceModule.name,
4559 detector->packageInfo.server.cleanFunctionName, lua_tostring(myLuaState, -1));
4560 #endif
4561 }
4562 }
4563 else if (detector->packageInfo.client.cleanFunctionName && lua_checkstack(myLuaState, 1))
4564 {
4565 lua_getglobal(myLuaState, detector->packageInfo.client.cleanFunctionName);
4566
4567 if (lua_pcall(myLuaState, 0, 0, 0 ))
4568 {
4569 /*See comment at first lua_pcall() */
4570 #ifdef LUA_DETECTOR_DEBUG
4571 _dpd.errMsg( "%s: error running %s in lua: %s", detector->server.serviceModule.name,
4572 detector->packageInfo.client.cleanFunctionName, lua_tostring(myLuaState, -1));
4573 #endif
4574 }
4575 }
4576
4577 freeDetector(detector);
4578
4579 /*lua_close will perform garbage collection after killing lua script. */
4580 /**Design: Lua_state does not allow me to store user variables so detectors store lua_state.
4581 * There is one lua_state for each lua file, which can have only one
4582 * detectors. So if lua detector creates a detector, registers a pattern
4583 * and then loses reference then lua will garbage collect but we should not free the buffer.
4584 *
4585 */
4586 lua_close(myLuaState);
4587 }
4588
4589
4590 /**Garbage collector hook function. Called when Lua side garbage collects detector api instance. Current design is to allocate
4591 * one of each luaState, detector and detectorUserData buffers, and hold these buffers till RNA exits. SigHups processing
4592 * reuses the buffers and calls DetectorInit to reinitialize. RNA ensures that DetectorUserData is not garbage collected, by
4593 * creating a reference in LUA_REGISTRY table. The reference is released only on RNA exit.
4594 *
4595 * If in future, one needs to free any of these buffers then one should consider references to detector buffer in RNAServiceElement
4596 * stored in flows and hostServices data structures. Other detectors at this time create one static instance for the lifetime of RNA,
4597 * and therefore we have adopted the same principle for Lua Detecotors.
4598 */
4599 static int Detector_gc (
4600 lua_State *L
4601 )
4602 {
4603 DetectorUserData *detectorUserData = toDetectorUserData(L, -1);
4604
4605 if (detectorUserData)
4606 {
4607 #ifdef LUA_DETECTOR_DEBUG
4608 _dpd.debugMsg(DEBUG_LOG,"DetectorUserData %p: freeing\n\n",detectorUserData);
4609 #endif
4610
4611 }
4612
4613 return 0;
4614 }
4615
4616 /*convert detector to string for printing */
4617 static int Detector_tostring (
4618 lua_State *L
4619 )
4620 {
4621 char buff[32];
4622 snprintf(buff, sizeof(buff), "%p", toDetectorUserData(L, 1));
4623 lua_pushfstring(L, "Detector (%s)", buff);
4624 return 1;
4625 }
4626
4627 static const luaL_Reg Detector_meta[] = {
4628 {"__gc", Detector_gc},
4629 {"__tostring", Detector_tostring},
4630 {0, 0}
4631 };
4632
4633
4634 /**Registers C functions as an API, enabling Lua detector to call these functions. This function
4635 * should be called once before loading any lua detectors. This function itself is not part of API
4636 * and therefore can not be called by a Lua detection.
4637 *
4638 * @param Lua_State* - Lua state variable.
4639 * @param detector/stack - detector object
4640 * @return int - Number of elements on stack, which is 1 if successful, 0 otherwise.
4641 * @return methodArray/stack - array of newly created methods
4642 */
4643 int Detector_register (
4644 lua_State *L
4645 )
4646 {
4647
4648 /* populates a new table with Detector_methods (method_table), add the table to the globals and stack*/
4649 luaL_openlib(L, DETECTOR, Detector_methods, 0);
4650
4651 /* create metatable for Foo, add it to the Lua registry, metatable on stack */
4652 luaL_newmetatable(L, DETECTOR);
4653
4654 /* populates table on stack with Detector_meta methods, puts the metatable on stack*/
4655 luaL_openlib(L, NULL, Detector_meta, 0);
4656
4657 lua_pushliteral(L, "__index");
4658 lua_pushvalue(L, -3); /* dup methods table*/
4659 lua_settable(L, -3); /* metatable.__index = methods */
4660
4661 lua_pushliteral(L, "__metatable");
4662 lua_pushvalue(L, -3); /* dup methods table*/
4663 lua_settable(L, -3); /* hide metatable:
4664 metatable.__metatable = methods */
4665 lua_pop(L, 1); /* drop metatable */
4666 return 1; /* return methods on the stack */
4667
4668
4669 }
4670
4671 /** @} */ /* end of LuaDetectorBaseApi */
4672
4673 static void FreeHTTPListElement(HTTPListElement *element)
4674 {
4675 if (element)
4676 {
4677 if (element->detectorHTTPPattern.pattern)
4678 free(element->detectorHTTPPattern.pattern);
4679 free(element);
4680 }
4681 }
4682
4683 static void FreeCHPAppListElement (CHPListElement *element)
4684 {
4685 if (element)
4686 {
4687 if (element->chp_action.pattern) free(element->chp_action.pattern);
4688 if (element->chp_action.action_data) free(element->chp_action.action_data);
4689 free (element);
4690 }
4691 }
4692
4693 static void FreeDetectorAppUrlPattern(DetectorAppUrlPattern *pattern)
4694 {
4695 if (pattern)
4696 {
4697 if (pattern->userData.query.pattern)
4698 free(*(void **)&pattern->userData.query.pattern);
4699 if (pattern->patterns.host.pattern)
4700 free(*(void **)&pattern->patterns.host.pattern);
4701 if (pattern->patterns.path.pattern)
4702 free(*(void **)&pattern->patterns.path.pattern);
4703 if (pattern->patterns.scheme.pattern)
4704 free(*(void **)&pattern->patterns.scheme.pattern);
4705 free(pattern);
4706 }
4707 }
4708
4709 void CleanHttpPatternLists(tAppIdConfig *pConfig)
4710 {
4711 HTTPListElement *element;
4712 CHPListElement *chpe;
4713 size_t i;
4714
4715 for (i = 0; i < pConfig->httpPatternLists.appUrlList.usedCount; i++)
4716 {
4717 FreeDetectorAppUrlPattern(pConfig->httpPatternLists.appUrlList.urlPattern[i]);
4718 pConfig->httpPatternLists.appUrlList.urlPattern[i] = NULL;
4719 }
4720 for (i = 0; i < pConfig->httpPatternLists.RTMPUrlList.usedCount; i++)
4721 {
4722 FreeDetectorAppUrlPattern(pConfig->httpPatternLists.RTMPUrlList.urlPattern[i]);
4723 pConfig->httpPatternLists.RTMPUrlList.urlPattern[i] = NULL;
4724 }
4725 if (pConfig->httpPatternLists.appUrlList.urlPattern)
4726 {
4727 free(pConfig->httpPatternLists.appUrlList.urlPattern);
4728 pConfig->httpPatternLists.appUrlList.urlPattern = NULL;
4729 }
4730 pConfig->httpPatternLists.appUrlList.allocatedCount = 0;
4731 if (pConfig->httpPatternLists.RTMPUrlList.urlPattern)
4732 {
4733 free(pConfig->httpPatternLists.RTMPUrlList.urlPattern);
4734 pConfig->httpPatternLists.RTMPUrlList.urlPattern = NULL;
4735 }
4736 pConfig->httpPatternLists.RTMPUrlList.allocatedCount = 0;
4737 pConfig->httpPatternLists.appUrlList.usedCount = 0;
4738 pConfig->httpPatternLists.RTMPUrlList.usedCount = 0;
4739 while ((element = pConfig->httpPatternLists.clientAgentPatternList))
4740 {
4741 pConfig->httpPatternLists.clientAgentPatternList = element->next;
4742 FreeHTTPListElement(element);
4743 }
4744 while ((element = pConfig->httpPatternLists.hostPayloadPatternList))
4745 {
4746 pConfig->httpPatternLists.hostPayloadPatternList = element->next;
4747 FreeHTTPListElement(element);
4748 }
4749 while ((element = pConfig->httpPatternLists.urlPatternList))
4750 {
4751 pConfig->httpPatternLists.urlPatternList = element->next;
4752 FreeHTTPListElement(element);
4753 }
4754 while ((element = pConfig->httpPatternLists.contentTypePatternList))
4755 {
4756 pConfig->httpPatternLists.contentTypePatternList = element->next;
4757 FreeHTTPListElement(element);
4758 }
4759 while ((chpe = pConfig->httpPatternLists.chpList))
4760 {
4761 pConfig->httpPatternLists.chpList = chpe->next;
4762 FreeCHPAppListElement(chpe);
4763 }
4764 }
4765