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(&current_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(&current_host->ipAddr.addr)
357                 );
358         }
359 
360         AppendApplicationData(&current_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(&current_host->ipAddr.addr)
371                 );
372         }
373 
374         AppendApplicationData(&current_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