1 /*
2 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 ** Copyright (C) 2006-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 * Author: Steven Sturges
23 * sftarget_reader.c
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #ifdef HAVE_GETTID
31 #define _GNU_SOURCE
32 #endif
33
34 #ifdef TARGET_BASED
35
36 #include <stdio.h>
37 #include "mstring.h"
38 #include "util.h"
39 #include "parser.h"
40 #include "sftarget_reader.h"
41 #include "sftarget_protocol_reference.h"
42 #include "sfutil/sfrt.h"
43 #include "sfutil/sfxhash.h"
44 #include "sfutil/util_net.h"
45 #include "sftarget_hostentry.h"
46
47 #include <signal.h>
48 #include <sys/types.h>
49 #include <stdlib.h>
50 #include <errno.h>
51 #include <pthread.h>
52 #include <unistd.h>
53 #include <time.h>
54
55 #ifndef WIN32
56 #include <sys/socket.h>
57 #include <netinet/in.h>
58 #include <arpa/inet.h>
59 #endif
60
61 #include "snort.h"
62
63 #include "snort_debug.h"
64 #include "sfPolicy.h"
65
66 typedef struct
67 {
68 table_t *lookupTable;
69 SFXHASH *mapTable;
70 } tTargetBasedConfig;
71
72 typedef struct
73 {
74 /**current configuration. */
75 tTargetBasedConfig curr;
76
77 /**previous configuration. */
78 tTargetBasedConfig prev;
79
80 /**next configuration. */
81 tTargetBasedConfig next;
82
83 //XXX recheck this flag usage
84 //char reload_attribute_table_flags;
85
86 } tTargetBasedPolicyConfig;
87
88
89 static tTargetBasedPolicyConfig targetBasedPolicyConfig;
90
91 static HostAttributeEntry *current_host = NULL;
92 static ApplicationEntry *current_app = NULL;
93
94 //static MapData *current_map_entry = NULL;
95 ServiceClient sfat_client_or_service;
96
97 extern char sfat_error_message[STD_BUF];
98 extern char sfat_grammar_error_printed;
99 extern char sfat_insufficient_space_logged;
100 extern char sfat_fatal_error;
101 int ParseTargetMap(char *filename);
102 void DestroyBufferStack(void);
103
104 extern char *sfat_saved_file;
105
106 extern pthread_t attribute_reload_thread_id;
107 extern pid_t attribute_reload_thread_pid;
108 extern volatile int attribute_reload_thread_running;
109 extern volatile int attribute_reload_thread_stop;
110 extern int reload_attribute_table_flags;
111 extern const struct timespec thread_sleep;
112
113 /*****TODO: cleanup to use config directive *******/
114 #define ATTRIBUTE_MAP_MAX_ROWS 1024
SFAT_NumberOfHosts(void)115 uint32_t SFAT_NumberOfHosts(void)
116 {
117 tTargetBasedPolicyConfig *pConfig = &targetBasedPolicyConfig;
118 if (pConfig->curr.lookupTable)
119 {
120 return sfrt_num_entries(pConfig->curr.lookupTable);
121 }
122
123 return 0;
124 }
125
SFAT_AddMapEntry(MapEntry * entry)126 int SFAT_AddMapEntry(MapEntry *entry)
127 {
128 tTargetBasedPolicyConfig *pConfig = &targetBasedPolicyConfig;
129
130 if (!pConfig->next.mapTable)
131 {
132 /* Attribute Table node includes memory for each entry,
133 * as defined by sizeof(MapEntry).
134 */
135 pConfig->next.mapTable = sfxhash_new(ATTRIBUTE_MAP_MAX_ROWS,
136 sizeof(int),
137 sizeof(MapEntry),
138 0,
139 1,
140 NULL,
141 NULL,
142 1);
143 if (!pConfig->next.mapTable)
144 FatalError("Failed to allocate attribute map table\n");
145 }
146
147 /* Memcopy MapEntry to newly allocated one and store in
148 * a hash table based on entry->id for easy lookup.
149 */
150
151 DEBUG_WRAP(
152 DebugMessage(DEBUG_ATTRIBUTE, "Adding Map Entry: %d %s\n",
153 entry->l_mapid, entry->s_mapvalue););
154
155 /* Data from entry will be copied into new node */
156 sfxhash_add(pConfig->next.mapTable, &entry->l_mapid, entry);
157
158 return SFAT_OK;
159 }
160
SFAT_LookupAttributeNameById(int id)161 char *SFAT_LookupAttributeNameById(int id)
162 {
163 MapEntry *entry;
164 tTargetBasedPolicyConfig *pConfig = &targetBasedPolicyConfig;
165
166 if (!pConfig->next.mapTable)
167 return NULL;
168
169 entry = sfxhash_find(pConfig->next.mapTable, &id);
170
171 if (entry)
172 {
173 DEBUG_WRAP(
174 DebugMessage(DEBUG_ATTRIBUTE, "Found Attribute Name %s for Id %d\n",
175 entry->s_mapvalue, id););
176 return entry->s_mapvalue;
177 }
178 DEBUG_WRAP(
179 DebugMessage(DEBUG_ATTRIBUTE, "No Attribute Name for Id %d\n", id););
180
181 return NULL;
182 }
183
FreeApplicationEntry(ApplicationEntry * app)184 void FreeApplicationEntry(ApplicationEntry *app)
185 {
186 DEBUG_WRAP(DebugMessage(DEBUG_ATTRIBUTE, "Freeing ApplicationEntry: 0x%x\n",
187 app););
188 free(app);
189 }
190
SFAT_CreateApplicationEntry(void)191 ApplicationEntry * SFAT_CreateApplicationEntry(void)
192 {
193 if (current_app)
194 {
195 /* Something went wrong */
196 FreeApplicationEntry(current_app);
197 current_app = NULL;
198 }
199
200 current_app = SnortAlloc(sizeof(ApplicationEntry));
201
202 return current_app;
203 }
204
SFAT_CreateHostEntry(void)205 HostAttributeEntry * SFAT_CreateHostEntry(void)
206 {
207 if (current_host)
208 {
209 /* Something went wrong */
210 FreeHostEntry(current_host);
211 current_host = NULL;
212 }
213
214 current_host = SnortAlloc(sizeof(HostAttributeEntry));
215
216 return current_host;
217 }
218
FreeHostEntry(HostAttributeEntry * host)219 void FreeHostEntry(HostAttributeEntry *host)
220 {
221 ApplicationEntry *app = NULL, *tmp_app;
222
223 if (!host)
224 return;
225
226 DEBUG_WRAP(DebugMessage(DEBUG_ATTRIBUTE, "Freeing HostEntry: 0x%x\n",
227 host););
228
229 /* Free the service list */
230 if (host->services)
231 {
232 do
233 {
234 tmp_app = host->services;
235 app = tmp_app->next;
236 FreeApplicationEntry(tmp_app);
237 host->services = app;
238 } while (app);
239 }
240
241 /* Free the client list */
242 if (host->clients)
243 {
244 do
245 {
246 tmp_app = host->clients;
247 app = tmp_app->next;
248 FreeApplicationEntry(tmp_app);
249 host->clients = app;
250 } while (app);
251 }
252
253 free(host);
254 }
255
PrintAttributeData(char * prefix,AttributeData * data)256 void PrintAttributeData(char *prefix, AttributeData *data)
257 {
258 #ifdef DEBUG_MSGS
259 DebugMessage(DEBUG_ATTRIBUTE, "AttributeData for %s\n", prefix);
260 if (data->type == ATTRIBUTE_NAME)
261 {
262 DebugMessage(DEBUG_ATTRIBUTE, "\ttype: %s\tname: %s\t confidence %d\n",
263 "Name", data->value.s_value, data->confidence);
264 }
265 else
266 {
267 DebugMessage(DEBUG_ATTRIBUTE, "\ttype: %s\tid: %s\t confidence %d",
268 "Id", data->value.l_value, data->confidence);
269 }
270 #endif
271 }
272
SFAT_SetHostIp(const char * ip)273 int SFAT_SetHostIp(const char *ip)
274 {
275 static HostAttributeEntry *tmp_host = NULL;
276 sfcidr_t ipAddr;
277 tTargetBasedPolicyConfig *pConfig = &targetBasedPolicyConfig;
278 SFAT_CHECKHOST;
279
280 if (sfip_pton(ip, &ipAddr) != SFIP_SUCCESS)
281 {
282 return SFAT_ERROR;
283 }
284
285 tmp_host = sfrt_lookup(&ipAddr.addr, pConfig->next.lookupTable);
286
287 if (tmp_host &&
288 sfip_equals(tmp_host->ipAddr.addr, ipAddr.addr))
289 {
290 /* Exact match. */
291 FreeHostEntry(current_host);
292 current_host = tmp_host;
293 }
294 else
295 {
296 /* New entry for this host/CIDR */
297 sfip_set_ip(¤t_host->ipAddr, &ipAddr);
298 }
299 return SFAT_OK;
300 }
301
SFAT_SetOSPolicy(char * policy_name,int attribute)302 int SFAT_SetOSPolicy(char *policy_name, int attribute)
303 {
304 SFAT_CHECKHOST;
305
306 switch (attribute)
307 {
308 case HOST_INFO_FRAG_POLICY:
309 SnortStrncpy(current_host->hostInfo.fragPolicyName, policy_name,
310 sizeof(current_host->hostInfo.fragPolicyName));
311 break;
312 case HOST_INFO_STREAM_POLICY:
313 SnortStrncpy(current_host->hostInfo.streamPolicyName, policy_name,
314 sizeof(current_host->hostInfo.streamPolicyName));
315 break;
316 }
317 return SFAT_OK;
318 }
319
SFAT_SetOSAttribute(AttributeData * data,int attribute)320 int SFAT_SetOSAttribute(AttributeData *data, int attribute)
321 {
322 SFAT_CHECKHOST;
323 // currently not using os, vendor, or version
324 return SFAT_OK;
325 }
326
AppendApplicationData(ApplicationList ** list)327 static void AppendApplicationData(ApplicationList **list)
328 {
329 if (!list)
330 return;
331
332 if (*list)
333 {
334 current_app->next = *list;
335 }
336 *list = current_app;
337 current_app = NULL;
338 }
339
340
SFAT_AddApplicationData(void)341 int SFAT_AddApplicationData(void)
342 {
343 uint8_t required_fields;
344 SFAT_CHECKAPP;
345 SFAT_CHECKHOST;
346
347 if (sfat_client_or_service == ATTRIBUTE_SERVICE)
348 {
349 required_fields = (APPLICATION_ENTRY_PORT |
350 APPLICATION_ENTRY_IPPROTO |
351 APPLICATION_ENTRY_PROTO);
352 if ((current_app->fields & required_fields) != required_fields)
353 {
354 FatalError("%s(%d): Missing required field in Service attribute table for host %s\n",
355 file_name, file_line,
356 sfip_to_str(¤t_host->ipAddr.addr)
357 );
358 }
359
360 AppendApplicationData(¤t_host->services);
361 }
362 else
363 {
364 required_fields = (APPLICATION_ENTRY_PROTO);
365 /* Currently, client data only includes PROTO, not IPPROTO */
366 if ((current_app->fields & required_fields) != required_fields)
367 {
368 FatalError("%s(%d): Missing required field in Client attribute table for host %s\n",
369 file_name, file_line,
370 sfip_to_str(¤t_host->ipAddr.addr)
371 );
372 }
373
374 AppendApplicationData(¤t_host->clients);
375 }
376 return SFAT_OK;
377 }
378
SFAT_SetApplicationAttribute(AttributeData * data,int attribute)379 int SFAT_SetApplicationAttribute(AttributeData *data, int attribute)
380 {
381 SFAT_CHECKAPP;
382
383 switch(attribute)
384 {
385 case APPLICATION_ENTRY_PORT:
386 /* Convert the port to a integer */
387 if (data->type == ATTRIBUTE_NAME)
388 {
389 char *endPtr = NULL;
390 unsigned long value = SnortStrtoul(data->value.s_value, &endPtr, 10);
391 if ((endPtr == &data->value.s_value[0]) ||
392 (errno == ERANGE) || value > UINT16_MAX)
393 {
394 current_app->port = 0;
395 return SFAT_ERROR;
396 }
397
398 current_app->port = (uint16_t)value;
399 }
400 else
401 {
402 if (data->value.l_value > UINT16_MAX)
403 {
404 current_app->port = 0;
405 return SFAT_ERROR;
406 }
407
408 current_app->port = (uint16_t)data->value.l_value;
409 }
410 break;
411 case APPLICATION_ENTRY_IPPROTO:
412 /* Add IP Protocol to the reference list */
413 current_app->ipproto = AddProtocolReference(data->value.s_value);
414 break;
415 case APPLICATION_ENTRY_PROTO:
416 /* Add Application Protocol to the reference list */
417 current_app->protocol = AddProtocolReference(data->value.s_value);
418 break;
419 // currently not using application or version
420 default:
421 attribute = 0;
422 }
423 current_app->fields |= attribute;
424
425 return SFAT_OK;
426 }
427
428 #ifdef DEBUG_MSGS
PrintHostAttributeEntry(HostAttributeEntry * host)429 void PrintHostAttributeEntry(HostAttributeEntry *host)
430 {
431 ApplicationEntry *app;
432 int i = 0;
433
434 if (!host)
435 return;
436
437 DebugMessage(DEBUG_ATTRIBUTE, "Host IP: %s/%d\n",
438 sfip_to_str(&host->ipAddr.addr),
439 (sfip_family(&host->ipAddr) == AF_INET) ? ((host->ipAddr.bits >= 96) ? (host->ipAddr.bits - 96) : -1) : host->ipAddr.bits
440 );
441 DebugMessage(DEBUG_ATTRIBUTE, "\tPolicy Information: frag:%s (%s %u) stream: %s (%s %u)\n",
442 host->hostInfo.fragPolicyName, host->hostInfo.fragPolicySet ? "set":"unset", host->hostInfo.fragPolicy,
443 host->hostInfo.fragPolicyName, host->hostInfo.streamPolicySet ? "set":"unset", host->hostInfo.streamPolicy);
444 DebugMessage(DEBUG_ATTRIBUTE, "\tServices:\n");
445 for (i=0, app = host->services; app; app = app->next,i++)
446 {
447 DebugMessage(DEBUG_ATTRIBUTE, "\tService #%d:\n", i);
448 DebugMessage(DEBUG_ATTRIBUTE, "\t\tIPProtocol: %s\tPort: %s\tProtocol %s\n",
449 app->ipproto, app->port, app->protocol);
450 }
451 if (i==0)
452 DebugMessage(DEBUG_ATTRIBUTE, "\t\tNone\n");
453
454 DebugMessage(DEBUG_ATTRIBUTE, "\tClients:\n");
455 for (i=0, app = host->clients; app; app = app->next,i++)
456 {
457 DebugMessage(DEBUG_ATTRIBUTE, "\tClient #%d:\n", i);
458 DebugMessage(DEBUG_ATTRIBUTE, "\t\tIPProtocol: %s\tProtocol %s\n",
459 app->ipproto, app->protocol);
460
461 if (app->fields & APPLICATION_ENTRY_PORT)
462 {
463 DebugMessage(DEBUG_ATTRIBUTE, "\t\tPort: %s\n", app->port);
464 }
465 }
466 if (i==0)
467 {
468 DebugMessage(DEBUG_ATTRIBUTE, "\t\tNone\n");
469 }
470 }
471 #endif
472
SFAT_AddHostEntryToMap(void)473 int SFAT_AddHostEntryToMap(void)
474 {
475 HostAttributeEntry *host = current_host;
476 int ret;
477 sfcidr_t *ipAddr;
478 tTargetBasedPolicyConfig *pConfig = &targetBasedPolicyConfig;
479
480 SFAT_CHECKHOST;
481
482 DEBUG_WRAP(PrintHostAttributeEntry(host););
483
484 ipAddr = &host->ipAddr;
485
486 ret = sfrt_insert(ipAddr, (unsigned char)ipAddr->bits, host,
487 RT_FAVOR_SPECIFIC, pConfig->next.lookupTable);
488
489 if (ret != RT_SUCCESS)
490 {
491 if (ret == RT_POLICY_TABLE_EXCEEDED)
492 {
493 if (!sfat_insufficient_space_logged)
494 {
495 SnortSnprintf(sfat_error_message, STD_BUF,
496 "AttributeTable insertion failed: %d Insufficient "
497 "space in attribute table, only configured to store %d hosts\n",
498 ret, ScMaxAttrHosts(snort_conf));
499 sfat_grammar_error_printed = 1;
500 sfat_insufficient_space_logged = 1;
501 sfat_fatal_error = 0;
502 }
503 /* Reset return value and continue w/ only snort_conf->max_attribute_hosts */
504 ret = RT_SUCCESS;
505 }
506 else
507 {
508 SnortSnprintf(sfat_error_message, STD_BUF,
509 "AttributeTable insertion failed: %d '%s'\n",
510 ret, rt_error_messages[ret]);
511 sfat_grammar_error_printed = 1;
512 }
513
514 FreeHostEntry(host);
515 }
516
517 current_host = NULL;
518
519 return ret == RT_SUCCESS ? SFAT_OK : SFAT_ERROR;
520 }
521
SFAT_LookupHostEntryByIP(sfaddr_t * ipAddr)522 HostAttributeEntry *SFAT_LookupHostEntryByIP(sfaddr_t *ipAddr)
523 {
524 tTargetBasedPolicyConfig *pConfig = NULL;
525 tSfPolicyId policyId = getNapRuntimePolicy();
526 HostAttributeEntry *host = NULL;
527
528 TargetBasedConfig *tbc = &snort_conf->targeted_policies[policyId]->target_based_config;
529
530 if (tbc->args == NULL)
531 {
532 //this policy didn't specify attribute_table
533 return NULL;
534 }
535
536 pConfig = &targetBasedPolicyConfig;
537
538 host = sfrt_lookup(ipAddr, pConfig->curr.lookupTable);
539
540 if (host)
541 {
542 /* Set the policy values for Frag & Stream if not already set */
543 //TODO: SetTargetBasedPolicy(host);
544 }
545
546 return host;
547 }
548
SFAT_LookupHostEntryBySrc(Packet * p)549 HostAttributeEntry *SFAT_LookupHostEntryBySrc(Packet *p)
550 {
551 if (!p || !p->iph_api)
552 return NULL;
553
554 return SFAT_LookupHostEntryByIP(GET_SRC_IP(p));
555 }
556
SFAT_LookupHostEntryByDst(Packet * p)557 HostAttributeEntry *SFAT_LookupHostEntryByDst(Packet *p)
558 {
559 if (!p || !p->iph_api)
560 return NULL;
561
562 return SFAT_LookupHostEntryByIP(GET_DST_IP(p));
563 }
564
565 static GetPolicyIdFunc updatePolicyCallback;
566 static GetPolicyIdsCallbackList *updatePolicyCallbackList = NULL;
SFAT_SetPolicyCallback(void * host_attr_ent)567 void SFAT_SetPolicyCallback(void *host_attr_ent)
568 {
569 HostAttributeEntry *host_entry = (HostAttributeEntry*)host_attr_ent;
570
571 if (!host_entry)
572 return;
573
574 updatePolicyCallback(host_entry);
575
576 return;
577 }
578
SFAT_SetPolicyIds(GetPolicyIdFunc policyCallback,int snortPolicyId)579 void SFAT_SetPolicyIds(GetPolicyIdFunc policyCallback, int snortPolicyId)
580 {
581 tTargetBasedPolicyConfig *pConfig = NULL;
582 GetPolicyIdsCallbackList *list_entry, *new_list_entry = NULL;
583
584 pConfig = &targetBasedPolicyConfig;
585
586 updatePolicyCallback = policyCallback;
587
588 sfrt_iterate(pConfig->curr.lookupTable, SFAT_SetPolicyCallback);
589
590 if (!updatePolicyCallbackList)
591 {
592 /* No list present, so no attribute table... bye-bye */
593 return;
594 }
595
596 /* Look for this callback in the list */
597 list_entry = updatePolicyCallbackList;
598 while (list_entry)
599 {
600 if (list_entry->policyCallback == policyCallback)
601 return; /* We're done with this one */
602
603 if (list_entry->next)
604 {
605 list_entry = list_entry->next;
606 }
607 else
608 {
609 /* Leave list_entry pointint to last node in list */
610 break;
611 }
612 }
613
614 /* Wasn't there, add it so that when we reload the table,
615 * we can set those policy entries on reload. */
616 new_list_entry = (GetPolicyIdsCallbackList *)SnortAlloc(sizeof(GetPolicyIdsCallbackList));
617 new_list_entry->policyCallback = policyCallback;
618 if (list_entry)
619 {
620 /* list_entry is valid here since there was at least an
621 * empty head entry in the list. */
622 list_entry->next = new_list_entry;
623 }
624 }
625
SFAT_CleanupCallback(void * host_attr_ent)626 void SFAT_CleanupCallback(void *host_attr_ent)
627 {
628 HostAttributeEntry *host_entry = (HostAttributeEntry*)host_attr_ent;
629 FreeHostEntry(host_entry);
630 }
631
SFAT_CleanPrevConfig(void)632 void SFAT_CleanPrevConfig(void)
633 {
634 tTargetBasedPolicyConfig *pConfig = &targetBasedPolicyConfig;
635
636 if (pConfig->prev.mapTable)
637 {
638 sfxhash_delete(pConfig->prev.mapTable);
639 pConfig->prev.mapTable = NULL;
640 }
641 if (pConfig->prev.lookupTable)
642 {
643 sfrt_cleanup(pConfig->prev.lookupTable, SFAT_CleanupCallback);
644 sfrt_free(pConfig->prev.lookupTable);
645 pConfig->prev.lookupTable = NULL;
646 }
647 reload_attribute_table_flags = 0;
648 }
649
SFAT_Cleanup(void)650 void SFAT_Cleanup(void)
651 {
652 GetPolicyIdsCallbackList *list_entry, *tmp_list_entry = NULL;
653
654 tTargetBasedPolicyConfig *pConfig = &targetBasedPolicyConfig;
655
656 if (pConfig->curr.mapTable)
657 {
658 sfxhash_delete(pConfig->curr.mapTable);
659 pConfig->curr.mapTable = NULL;
660 }
661
662 if (pConfig->prev.mapTable)
663 {
664 sfxhash_delete(pConfig->prev.mapTable);
665 pConfig->prev.mapTable = NULL;
666 }
667
668 if (pConfig->next.mapTable)
669 {
670 sfxhash_delete(pConfig->next.mapTable);
671 pConfig->next.mapTable = NULL;
672 }
673
674 if (pConfig->curr.lookupTable)
675 {
676 sfrt_cleanup(pConfig->curr.lookupTable, SFAT_CleanupCallback);
677 sfrt_free(pConfig->curr.lookupTable);
678 pConfig->curr.lookupTable = NULL;
679 }
680
681 if (pConfig->prev.lookupTable)
682 {
683 sfrt_cleanup(pConfig->prev.lookupTable, SFAT_CleanupCallback);
684 sfrt_free(pConfig->prev.lookupTable);
685 pConfig->prev.lookupTable = NULL;
686 }
687
688 if (pConfig->next.lookupTable)
689 {
690 sfrt_cleanup(pConfig->next.lookupTable, SFAT_CleanupCallback);
691 sfrt_free(pConfig->next.lookupTable);
692 pConfig->next.lookupTable = NULL;
693 }
694
695 if (sfat_saved_file)
696 {
697 free(sfat_saved_file);
698 sfat_saved_file = NULL;
699 }
700
701 if (updatePolicyCallbackList)
702 {
703 list_entry = updatePolicyCallbackList;
704 while (list_entry)
705 {
706 tmp_list_entry = list_entry->next;
707 free(list_entry);
708 list_entry = tmp_list_entry;
709 }
710 updatePolicyCallbackList = NULL;
711 }
712
713 DestroyBufferStack();
714 }
715
716 #define set_attribute_table_flag(flag) \
717 reload_attribute_table_flags |= flag;
718 #define clear_attribute_table_flag(flag) \
719 reload_attribute_table_flags &= ~flag;
720 #define check_attribute_table_flag(flag) \
721 (reload_attribute_table_flags & flag)
722
SigAttributeTableReloadHandler(int signal)723 void SigAttributeTableReloadHandler(int signal)
724 {
725 /* If we're already reloading, don't do anything. */
726 if (check_attribute_table_flag(ATTRIBUTE_TABLE_RELOADING_FLAG))
727 return;
728
729 /* Set flag to reload attribute table */
730 set_attribute_table_flag(ATTRIBUTE_TABLE_RELOAD_FLAG);
731 }
732
SFAT_VTAlrmHandler(int signal)733 void SFAT_VTAlrmHandler(int signal)
734 {
735 /* Do nothing, just used to wake the sleeping dog... */
736 return;
737 }
738
SFAT_ReloadAttributeTableThread(void * arg)739 void *SFAT_ReloadAttributeTableThread(void *arg)
740 {
741 #ifndef WIN32
742 sigset_t mtmask, oldmask;
743 int ret;
744 int reloads = 0;
745 tTargetBasedPolicyConfig *pConfig = NULL;
746
747 pConfig = &targetBasedPolicyConfig;
748
749 sigemptyset(&mtmask);
750 attribute_reload_thread_pid = gettid();
751
752 /* Get the current set of signals inherited from main thread.*/
753 pthread_sigmask(SIG_UNBLOCK, &mtmask, &oldmask);
754
755 /* Now block those signals from being delivered to this thread.
756 * now Main receives all signals. */
757 pthread_sigmask(SIG_BLOCK, &oldmask, NULL);
758
759 /* And allow SIGVTALRM through */
760 signal (SIGVTALRM, SFAT_VTAlrmHandler); if(errno!=0) errno=0;
761 sigemptyset(&mtmask);
762 sigaddset(&mtmask, SIGVTALRM);
763 pthread_sigmask(SIG_UNBLOCK, &mtmask, NULL);
764
765 attribute_reload_thread_running = 1;
766 attribute_reload_thread_stop = 0;
767
768 /* Checks the flag and terminates the attribute reload thread.
769 *
770 * Receipt of VTALRM signal pulls it out of the idle sleep (at
771 * bottom of while(). Thread exits normally on next iteration
772 * through its loop because stop flag is set.
773 */
774 while (!attribute_reload_thread_stop)
775 {
776 #ifdef DEBUG_MSGS
777 DebugMessage(DEBUG_ATTRIBUTE,
778 "AttrReloadThread: Checking for new attr table...\n");
779 #endif
780 ret = SFAT_ERROR;
781
782 /* Is there an old table waiting to be cleaned up? */
783 if (check_attribute_table_flag(ATTRIBUTE_TABLE_TAKEN_FLAG))
784 {
785 if (check_attribute_table_flag(ATTRIBUTE_TABLE_AVAILABLE_FLAG))
786 {
787 #ifdef DEBUG_MSGS
788 DebugMessage(DEBUG_ATTRIBUTE,
789 "AttrReloadThread: Freeing old attr table...\n");
790 #endif
791 /* Free the map and attribute tables that are stored in
792 * prev.mapTable and prev.lookupTable */
793 sfxhash_delete(pConfig->prev.mapTable);
794 pConfig->prev.mapTable = NULL;
795
796 sfrt_cleanup(pConfig->prev.lookupTable, SFAT_CleanupCallback);
797 sfrt_free(pConfig->prev.lookupTable);
798 pConfig->prev.lookupTable = NULL;
799 clear_attribute_table_flag(ATTRIBUTE_TABLE_AVAILABLE_FLAG);
800 }
801 clear_attribute_table_flag(ATTRIBUTE_TABLE_PARSE_FAILED_FLAG);
802 clear_attribute_table_flag(ATTRIBUTE_TABLE_TAKEN_FLAG);
803 continue;
804 }
805 else if (check_attribute_table_flag(ATTRIBUTE_TABLE_RELOAD_FLAG) &&
806 !check_attribute_table_flag(ATTRIBUTE_TABLE_AVAILABLE_FLAG) &&
807 !check_attribute_table_flag(ATTRIBUTE_TABLE_PARSE_FAILED_FLAG))
808 {
809 /* Is there an new table ready? */
810 set_attribute_table_flag(ATTRIBUTE_TABLE_RELOADING_FLAG);
811 #ifdef DEBUG_MSGS
812 DebugMessage(DEBUG_ATTRIBUTE,
813 "AttrReloadThread: loading new attr table.\n");
814 #endif
815 reloads++;
816 if (sfat_saved_file)
817 {
818 /* Initialize a new lookup table */
819 if (!pConfig->next.lookupTable)
820 {
821 /* Add 1 to max for table purposes
822 * We use max_hosts to limit memcap, assume 16k per entry costs*/
823 pConfig->next.lookupTable =
824 sfrt_new(DIR_8x16, IPv6, ScMaxAttrHosts(snort_conf) + 1,
825 ((ScMaxAttrHosts(snort_conf))>>6) + 1);
826 if (!pConfig->next.lookupTable)
827 {
828 SnortSnprintf(sfat_error_message, STD_BUF,
829 "Failed to initialize memory for new attribute table\n");
830 clear_attribute_table_flag(ATTRIBUTE_TABLE_RELOAD_FLAG);
831 clear_attribute_table_flag(ATTRIBUTE_TABLE_RELOADING_FLAG);
832 set_attribute_table_flag(ATTRIBUTE_TABLE_PARSE_FAILED_FLAG);
833 continue;
834 }
835 }
836 ret = ParseTargetMap(sfat_saved_file);
837 if (ret == SFAT_OK)
838 {
839 GetPolicyIdsCallbackList *list_entry = NULL;
840 /* Set flag that a new table is available. Main
841 * process will check that flag and do the swap.
842 * After the new table is in use, the available
843 * flag should be cleared, the taken flag gets set
844 * and we'll go off and free the old one.
845 */
846
847 /* Set the policy IDs in the new table... */
848 list_entry = (GetPolicyIdsCallbackList *)arg;
849 while (list_entry)
850 {
851 if (list_entry->policyCallback)
852 {
853 sfrt_iterate(pConfig->next.lookupTable,
854 (sfrt_iterator_callback)list_entry->policyCallback);
855 }
856 list_entry = list_entry->next;
857 }
858
859 set_attribute_table_flag(ATTRIBUTE_TABLE_AVAILABLE_FLAG);
860 }
861 else
862 {
863 /* Failed to parse, clean it up */
864 if (pConfig->next.mapTable)
865 sfxhash_delete(pConfig->next.mapTable);
866 pConfig->next.mapTable = NULL;
867
868 sfrt_cleanup(pConfig->next.lookupTable, SFAT_CleanupCallback);
869 sfrt_free(pConfig->next.lookupTable);
870 pConfig->next.lookupTable = NULL;
871
872 set_attribute_table_flag(ATTRIBUTE_TABLE_PARSE_FAILED_FLAG);
873 }
874 }
875 clear_attribute_table_flag(ATTRIBUTE_TABLE_RELOAD_FLAG);
876 clear_attribute_table_flag(ATTRIBUTE_TABLE_RELOADING_FLAG);
877 }
878 else
879 {
880 /* Sleep for 60 seconds */
881 #ifdef DEBUG_MSGS
882 DebugMessage(DEBUG_ATTRIBUTE,
883 "AttrReloadThread: Checked for new attr table... sleeping.\n");
884 #endif
885 sleep(60);
886 }
887 }
888 #ifdef DEBUG_MSGS
889 DebugMessage(DEBUG_ATTRIBUTE,
890 "AttrReloadThread: exiting... Handled %d reloads\n", reloads);
891 #endif
892
893 attribute_reload_thread_running = 0;
894 pthread_exit(NULL);
895 #endif /* !Win32 */
896 return NULL;
897 }
898
AttributeTableReloadCheck(void)899 void AttributeTableReloadCheck(void)
900 {
901 tTargetBasedPolicyConfig *pConfig = NULL;
902
903 pConfig = &targetBasedPolicyConfig;
904
905 if (check_attribute_table_flag(ATTRIBUTE_TABLE_TAKEN_FLAG))
906 {
907 return; /* Nothing to do, waiting for thread to clear this
908 * flag... */
909 }
910 /* Swap the attribute table pointers. */
911 else if ((pConfig != NULL) &&
912 check_attribute_table_flag(ATTRIBUTE_TABLE_AVAILABLE_FLAG))
913 {
914 LogMessage("Swapping Attribute Tables.\n");
915 /***Do this on receipt of new packet ****/
916 /***Avoids need for mutex****/
917 pConfig->prev.lookupTable = pConfig->curr.lookupTable;
918 pConfig->curr.lookupTable = pConfig->next.lookupTable;
919 pConfig->next.lookupTable = NULL;
920
921 pConfig->prev.mapTable = pConfig->curr.mapTable;
922 pConfig->curr.mapTable = pConfig->next.mapTable;
923 pConfig->next.mapTable = NULL;
924
925 /* Set taken to indicate we've taken the new table */
926 set_attribute_table_flag(ATTRIBUTE_TABLE_TAKEN_FLAG);
927
928 sfBase.iAttributeHosts = SFAT_NumberOfHosts();
929 sfBase.iAttributeReloads++;
930 pc.attribute_table_reloads++;
931 }
932 else if (check_attribute_table_flag(ATTRIBUTE_TABLE_PARSE_FAILED_FLAG))
933 {
934 LogMessage("%s", sfat_error_message);
935 /* Set taken to indicate we've taken the error message */
936 set_attribute_table_flag(ATTRIBUTE_TABLE_TAKEN_FLAG);
937 }
938 }
939
940 /**called once during initialization. Reads attribute table for the first time.*/
SFAT_ParseAttributeTable(char * args,SnortConfig * sc)941 int SFAT_ParseAttributeTable(char *args, SnortConfig *sc)
942 {
943 char **toks;
944 int num_toks;
945 int ret;
946 tTargetBasedPolicyConfig *pConfig = &targetBasedPolicyConfig;
947
948 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"AttributeTable\n"););
949
950
951 /* Initialize lookup table */
952 if (!pConfig->next.lookupTable)
953 {
954 /* Add 1 to max for table purposes
955 * We use max_hosts to limit memcap, assume 16k per entry costs*/
956 pConfig->next.lookupTable =
957 sfrt_new(DIR_8x16, IPv6, ScMaxAttrHosts(sc) + 1,
958 ((ScMaxAttrHosts(sc))>>6)+ 1);
959 if (!pConfig->next.lookupTable)
960 {
961 FatalError("Failed to initialize attribute table memory\n");
962 }
963 }
964
965 /* Parse filename */
966 toks = mSplit(args, " \t", 0, &num_toks, 0);
967
968 if (num_toks != 2)
969 {
970 FatalError("%s(%d) ==> attribute_table must have 2 parameters\n",
971 file_name, file_line);
972 }
973
974 if (!(strcasecmp(toks[0], "filename") == 0))
975 {
976 FatalError("%s(%d) ==> attribute_table must have 2 arguments, the 1st "
977 "is 'filename'\n",
978 file_name, file_line);
979 }
980
981 /* Reset... */
982 sfat_insufficient_space_logged = 0;
983 sfat_fatal_error = 1;
984
985 ret = ParseTargetMap(toks[1]);
986
987 if (ret == SFAT_OK)
988 {
989 pConfig->curr.lookupTable = pConfig->next.lookupTable;
990 pConfig->next.lookupTable = NULL;
991 pConfig->curr.mapTable = pConfig->next.mapTable;
992 pConfig->next.mapTable = NULL;
993 if (sfat_insufficient_space_logged)
994 LogMessage("%s", sfat_error_message);
995 }
996 else
997 {
998 LogMessage("%s", sfat_error_message);
999 if (sfat_fatal_error)
1000 FatalError("%s(%d) ==> failed to load attribute table from %s\n",
1001 file_name, file_line, toks[1]);
1002 }
1003 mSplitFree(&toks, num_toks);
1004
1005 /* Create Thread to handle reparsing stuff... */
1006 sfBase.iAttributeHosts = SFAT_NumberOfHosts();
1007 LogMessage("Attribute Table Loaded with " STDu64 " hosts\n", sfBase.iAttributeHosts);
1008
1009 /* Set up the head (empty) node in the policy callback list to
1010 * pass to thread.*/
1011 updatePolicyCallbackList = (GetPolicyIdsCallbackList *)SnortAlloc(sizeof(GetPolicyIdsCallbackList));
1012
1013 return SFAT_OK;
1014 }
1015
SFAT_StartReloadThread(void)1016 void SFAT_StartReloadThread(void)
1017 {
1018 #ifndef WIN32
1019
1020 LogMessage("Attribute Table Reload Thread Starting...\n");
1021
1022 if (pthread_create(&attribute_reload_thread_id, NULL,
1023 SFAT_ReloadAttributeTableThread, updatePolicyCallbackList))
1024 {
1025 FatalError("Failed to start thread to handle reloading attribute table\n");
1026 }
1027
1028 while (!attribute_reload_thread_running)
1029 nanosleep(&thread_sleep, NULL);
1030
1031 LogMessage("Attribute Table Reload Thread Started, thread %p (%u)\n",
1032 (void*)attribute_reload_thread_id, attribute_reload_thread_pid);
1033 #endif
1034 }
1035
IsAdaptiveConfigured(void)1036 int IsAdaptiveConfigured( void )
1037 {
1038 SnortConfig *sc = snort_conf;
1039 tSfPolicyId id = getDefaultPolicy( );
1040
1041 if (id >= sc->num_policies_allocated)
1042 {
1043 ErrorMessage("%s(%d) Policy id is greater than the number of policies "
1044 "allocated.\n", __FILE__, __LINE__);
1045 return 0;
1046 }
1047
1048 if ((sc->targeted_policies[id] == NULL) ||
1049 (sc->targeted_policies[id]->target_based_config.args == NULL))
1050 {
1051 return 0;
1052 }
1053
1054 return 1;
1055 }
1056
IsAdaptiveConfiguredForSnortConfig(struct _SnortConfig * sc)1057 int IsAdaptiveConfiguredForSnortConfig(struct _SnortConfig *sc)
1058 {
1059 tSfPolicyId id = getDefaultPolicy( );
1060
1061 if (sc == NULL)
1062 {
1063 FatalError("%s(%d) Snort conf for parsing is NULL.\n",
1064 __FILE__, __LINE__);
1065 }
1066
1067 if (id >= sc->num_policies_allocated)
1068 {
1069 ErrorMessage("%s(%d) Policy id is greater than the number of policies "
1070 "allocated.\n", __FILE__, __LINE__);
1071 return 0;
1072 }
1073
1074 if ((sc->targeted_policies[id] == NULL) ||
1075 (sc->targeted_policies[id]->target_based_config.args == NULL))
1076 {
1077 return 0;
1078 }
1079
1080 return 1;
1081 }
1082
SFAT_UpdateApplicationProtocol(sfaddr_t * ipAddr,uint16_t port,uint16_t protocol,uint16_t id)1083 void SFAT_UpdateApplicationProtocol(sfaddr_t *ipAddr, uint16_t port, uint16_t protocol, uint16_t id)
1084 {
1085 HostAttributeEntry *host_entry;
1086 ApplicationEntry *service;
1087 tTargetBasedPolicyConfig *pConfig = &targetBasedPolicyConfig;
1088 unsigned service_count = 0;
1089 int rval;
1090
1091 pConfig = &targetBasedPolicyConfig;
1092
1093 host_entry = sfrt_lookup(ipAddr, pConfig->curr.lookupTable);
1094
1095 if (!host_entry)
1096 {
1097 GetPolicyIdsCallbackList *list_entry;
1098
1099 if (sfrt_num_entries(pConfig->curr.lookupTable) >= ScMaxAttrHosts(snort_conf))
1100 return;
1101
1102 host_entry = SnortAlloc(sizeof(*host_entry));
1103 sfip_set_ip(&host_entry->ipAddr.addr, ipAddr);
1104 host_entry->ipAddr.bits = 128;
1105 if ((rval = sfrt_insert(&host_entry->ipAddr, (unsigned char)host_entry->ipAddr.bits, host_entry,
1106 RT_FAVOR_SPECIFIC, pConfig->curr.lookupTable)) != RT_SUCCESS)
1107 {
1108 FreeHostEntry(host_entry);
1109 return;
1110 }
1111 for (list_entry = updatePolicyCallbackList; list_entry; list_entry = list_entry->next)
1112 {
1113 if (list_entry->policyCallback)
1114 list_entry->policyCallback(host_entry);
1115 }
1116 service = NULL;
1117 }
1118 else
1119 {
1120 for (service = host_entry->services; service; service = service->next)
1121 {
1122 if (service->ipproto == protocol && (uint16_t)service->port == port)
1123 {
1124 break;
1125 }
1126 service_count++;
1127 }
1128 }
1129 if (!service)
1130 {
1131 if ( service_count >= ScMaxAttrServicesPerHost() )
1132 return;
1133
1134 service = SnortAlloc(sizeof(*service));
1135 service->port = port;
1136 service->ipproto = protocol;
1137 service->next = host_entry->services;
1138 host_entry->services = service;
1139 service->protocol = id;
1140 }
1141 else if (service->protocol != id)
1142 {
1143 service->protocol = id;
1144 }
1145 }
1146
1147 #ifdef SNORT_RELOAD
SFAT_ReloadCheck(SnortConfig * sc)1148 void SFAT_ReloadCheck(SnortConfig *sc)
1149 {
1150 /* Adaptive profile has changed from OFF -> ON */
1151 if(!IsAdaptiveConfiguredForSnortConfig(snort_conf) && IsAdaptiveConfiguredForSnortConfig(sc))
1152 {
1153 tSfPolicyId defaultPolicyId = sfGetDefaultPolicy(sc->policy_config);
1154 TargetBasedConfig *tbc = &sc->targeted_policies[defaultPolicyId]->target_based_config;
1155
1156 if (tbc && tbc->args)
1157 {
1158 SFAT_ParseAttributeTable(tbc->args, sc);
1159 }
1160
1161 if(!(sc->run_flags & RUN_FLAG__DISABLE_ATTRIBUTE_RELOAD_THREAD))
1162 SFAT_StartReloadThread();
1163 #ifdef REG_TEST
1164 if(REG_TEST_FLAG_RELOAD & getRegTestFlags())
1165 {
1166 printf("Adaptive profile enabled, started attribute reload thread.\n");
1167 }
1168 #endif
1169 }
1170 /* Adaptive profile already ON, enabled profile updates */
1171 else if(IsAdaptiveConfiguredForSnortConfig(snort_conf) && IsAdaptiveConfiguredForSnortConfig(sc))
1172 {
1173 if((snort_conf->run_flags & RUN_FLAG__DISABLE_ATTRIBUTE_RELOAD_THREAD) &&
1174 !(sc->run_flags & RUN_FLAG__DISABLE_ATTRIBUTE_RELOAD_THREAD))
1175 {
1176 SFAT_StartReloadThread();
1177 }
1178 }
1179 }
1180
ReloadAttributeThreadStop(void)1181 void ReloadAttributeThreadStop(void)
1182 {
1183 // Stop the attribute reload thread
1184 if (attribute_reload_thread_running)
1185 {
1186 /* Doing same stuff that is done in SnortCleanup()
1187 */
1188 LogMessage("Terminating attribute reload thread\n");
1189 attribute_reload_thread_stop = 1;
1190 pthread_kill(attribute_reload_thread_id, SIGVTALRM);
1191 pthread_join(attribute_reload_thread_id, NULL);
1192 }
1193 }
1194 #endif
1195
1196 #endif /* TARGET_BASED */
1197
1198