int Load_As_Config(HWND hWnd, HINSTANCE hInst) { char Name[2048]; OPENFILENAME ofn; SetCurrentDirectoryA(thisprocessPath); strcpy(&Name[0], defaultConfigFilename); memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.hInstance = hInst; ofn.lpstrFile = Name; ofn.nMaxFile = 2047; ofn.lpstrFilter = "Config Files\0*.cfg\0All Files\0*.*\0\0"; ofn.nFilterIndex = 1; ofn.lpstrInitialDir = thisprocessPath; ofn.lpstrDefExt = "cfg"; ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if(GetOpenFileName(&ofn)) { Load_Config(Name); return 1; } else return 0; }
bool AtlasResourceCompiler::Should_Compile() { Platform* platform = Platform::Get(); // If input dosen't exist, the wtf. if (!platform->Is_File(m_input_path.c_str())) { DBG_ASSERT_STR(false, "Attempt to compile non-existing resource '%s'.", m_input_path.c_str()); return false; } // If input has been modified, compile is definitely required. if (Check_File_Timestamp(m_input_path)) { return true; } // Read in the XML, so we can determine if there are any other dependent files. if (!Load_Config()) { return false; } // Check dependent files. for (std::vector<std::string>::iterator iter = m_dependent_files.begin(); iter != m_dependent_files.end(); iter++) { std::string& path = *iter; if (Check_File_Timestamp(path.c_str())) { return true; } } return false; }
int main(int argc, char **argv) { const struct option long_options[] = { { "help", no_argument, NULL, 'h' }, { "debug", required_argument, NULL, 'd' }, { "daemon", no_argument, NULL, 'D' }, { "user", required_argument, NULL, 'u' }, { "chroot", required_argument, NULL, 'c' }, { "credits", no_argument, NULL, 'C' }, { "config", required_argument, NULL, 'f' }, { "log", required_argument, NULL, 'l' }, { "file", required_argument, NULL, 'F' }, {0, 0, 0, 0} }; static const char *short_options = "l:f:u:d:c:pDhC"; int option_index = 0; /****************************************************************************/ /* libpcap/PLOG (syslog sniffer) local variables */ /****************************************************************************/ #ifdef HAVE_LIBPCAP pthread_t pcap_thread; pthread_attr_t thread_pcap_attr; pthread_attr_init(&thread_pcap_attr); pthread_attr_setdetachstate(&thread_pcap_attr, PTHREAD_CREATE_DETACHED); #endif /****************************************************************************/ /* Perfmonitor local variables */ /****************************************************************************/ pthread_t perfmonitor_thread; pthread_attr_t thread_perfmonitor_attr; pthread_attr_init(&thread_perfmonitor_attr); pthread_attr_setdetachstate(&thread_perfmonitor_attr, PTHREAD_CREATE_DETACHED); /****************************************************************************/ /* Various local variables */ /****************************************************************************/ /* Block all signals, we create a signal handling thread */ sigset_t signal_set; pthread_t sig_thread; sigfillset( &signal_set ); pthread_sigmask( SIG_BLOCK, &signal_set, NULL ); /* Key board handler (displays stats, etc */ pthread_t key_thread; pthread_attr_t key_thread_attr; pthread_attr_init(&key_thread_attr); pthread_attr_setdetachstate(&key_thread_attr, PTHREAD_CREATE_DETACHED); struct sockaddr_in sa; char src_dns_lookup[20]; int dns_flag=0; sbool fifoerr=0; char *syslog_host=NULL; char *syslog_facility=NULL; char *syslog_priority=NULL; char *syslog_level=NULL; char *syslog_tag=NULL; char *syslog_date=NULL; char *syslog_time=NULL; char *syslog_program=NULL; char *syslog_msg=NULL; char syslogstring[MAX_SYSLOGMSG]; signed char c; char *tok; int rc=0; int i; time_t t; struct tm *run; sbool debugflag=0; /* Allocate and clear memory for global structs */ /* Allocate memory for global struct _SaganDebug */ debug = malloc(sizeof(_SaganDebug)); memset(debug, 0, sizeof(_SaganDebug)); /* Allocate memroy for global struct _SaganConfig */ config = malloc(sizeof(_SaganConfig)); memset(config, 0, sizeof(_SaganConfig)); struct _SaganSigArgs *sigargs; sigargs = malloc(sizeof(_SaganSigArgs)); memset(sigargs, 0, sizeof(_SaganSigArgs)); struct _SaganDNSCache *dnscache; dnscache = malloc(sizeof(_SaganDNSCache)); memset(dnscache, 0, sizeof(_SaganDNSCache)); counters = malloc(sizeof(_SaganCounters)); memset(counters, 0, sizeof(_SaganCounters)); flowbit = malloc(sizeof(_Sagan_Flowbit)); memset(flowbit, 0, sizeof(_Sagan_Flowbit)); t = time(NULL); run=localtime(&t); strftime(config->sagan_startutime, sizeof(config->sagan_startutime), "%s", run); strlcpy(config->sagan_config, CONFIG_FILE_PATH, sizeof(config->sagan_config)); /* We set the config->sagan_log_filepath to the system default. It'll be fopen'ed shortly - 06/03/2011 - Champ Clark III */ strlcpy(config->sagan_log_filepath, SAGANLOG, sizeof(config->sagan_log_filepath)); config->sagan_runas = RUNAS; /* Get command line arg's */ while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) { switch(c) { if (c == -1) break; case 'h': Sagan_Usage(); exit(0); break; case 'C': Sagan_Credits(); exit(0); break; case 'd': if (Sagan_strstr(optarg, "malformed")) { debug->debugmalformed=1; debugflag=1; } if (Sagan_strstr(optarg, "limits")) { debug->debuglimits=1; debugflag=1; } if (Sagan_strstr(optarg, "syslog")) { debug->debugsyslog=1; debugflag=1; } if (Sagan_strstr(optarg, "load")) { debug->debugload=1; debugflag=1; } if (Sagan_strstr(optarg, "fwsam")) { debug->debugfwsam=1; debugflag=1; } if (Sagan_strstr(optarg, "external")) { debug->debugexternal=1; debugflag=1; } if (Sagan_strstr(optarg, "threads")) { debug->debugthreads=1; debugflag=1; } if (Sagan_strstr(optarg, "flowbit")) { debug->debugflowbit=1; debugflag=1; } if (Sagan_strstr(optarg, "engine")) { debug->debugengine=1; debugflag=1; } if (Sagan_strstr(optarg, "brointel")) { debug->debugbrointel=1; debugflag=1; } #ifdef HAVE_LIBGEOIP if (Sagan_strstr(optarg, "geoip")) { debug->debuggeoip=1; debugflag=1; } #endif #ifdef HAVE_LIBLOGNORM if (Sagan_strstr(optarg, "normalize" )) { debug->debugnormalize=1; debugflag=1; } #endif #ifdef HAVE_LIBESMTP if (Sagan_strstr(optarg, "smtp")) { debug->debugesmtp=1; debugflag=1; } #endif #ifdef HAVE_LIBPCAP if (Sagan_strstr(optarg, "plog")) { debug->debugplog=1; debugflag=1; } #endif #ifdef WITH_WEBSENSE if (Sagan_strstr(optarg, "websense")) { debug->debugwebsense=1; debugflag=1; } #endif /* If option is unknown */ if ( debugflag == 0 ) { fprintf(stderr, "Unknown debug option %s!\n", optarg); exit(1); } break; case 'D': daemonize=1; break; case 'u': config->sagan_runas=optarg; break; case 'c': Sagan_Chroot(optarg); break; case 'F': config->sagan_fifo_flag=1; strlcpy(config->sagan_fifo,optarg,sizeof(config->sagan_fifo) - 1); break; case 'f': strlcpy(config->sagan_config,optarg,sizeof(config->sagan_config) - 1); break; case 'l': strlcpy(config->sagan_log_filepath,optarg,sizeof(config->sagan_log_filepath) - 1); break; default: fprintf(stderr, "Invalid argument! See below for command line switches.\n"); Sagan_Usage(); exit(0); break; } } Sagan_Open_Log_File(OPEN, SAGAN_LOG); Load_Config(); Sagan_Engine_Init(); #ifdef HAVE_LIBLOGNORM Sagan_Liblognorm_Load(); #endif /* Load/init liblognorm definitions. I tried to move this into a subroutine, * but that ended up causing segfaults on ln_normalize() or causing * liblognorm not to function correctly (not parsing fields). Make reloading * a SIGHUP a issue as well. * 12/17/2010 - Champ */ SaganProcSyslog = malloc(config->max_processor_threads * sizeof(struct _Sagan_Proc_Syslog)); pthread_t processor_id[config->max_processor_threads]; pthread_attr_t thread_processor_attr; pthread_attr_init(&thread_processor_attr); pthread_attr_setdetachstate(&thread_processor_attr, PTHREAD_CREATE_DETACHED); Sagan_Log(S_NORMAL, "Configuration file %s loaded and %d rules loaded.", config->sagan_config, counters->rulecount); Sagan_Log(S_NORMAL, "Out of %d rules, %d Flowbit(s) are in use.", counters->rulecount, counters->flowbit_total_counter); Sagan_Log(S_NORMAL, "Sagan version %s is firing up!", VERSION); /* We go ahead and assign values to SaganSigArgs (struct sig_thread_args). This * struct is always used by the sig_handler thread, and sometimes used by the * plog_handler (below). So we assign values now */ sigargs->daemonize = daemonize; #ifdef HAVE_LIBPCAP /* Spawn a thread to 'sniff' syslog traffic (sagan-plog.c). This redirects syslog traffic to the /dev/log socket. This needs "root" access, so we drop priv's after this thread is started */ if ( config->plog_flag ) { rc = pthread_create( &pcap_thread, NULL, (void *)plog_handler, sigargs ); if ( rc != 0 ) { Remove_Lock_File(); Sagan_Log(S_ERROR, "[%s, line %d] Error creating libpcap handler thread [error: %d].", __FILE__, __LINE__, rc); } sleep(1); /* Sleep to avoid race between main() and plog thread plog thread needs "root" rights before sagan_droppriv(). In some cases main() run sagan_droppriv() before thread can complete - Champ Clark - 07/20/2011 */ } #endif Sagan_Droppriv(); /* Become the Sagan user */ Sagan_Log(S_NORMAL, "---------------------------------------------------------------------------"); if ( config->perfmonitor_flag ) { if (( config->perfmonitor_file_stream = fopen(config->perfmonitor_file_name, "a" )) == NULL ) { Remove_Lock_File(); Sagan_Log(S_ERROR, "[%s, line %d] Can't open %s - %s!", __FILE__, __LINE__, config->perfmonitor_file_name, strerror(errno)); } rc = pthread_create( &perfmonitor_thread, NULL, (void *)Sagan_Perfmonitor_Handler, sigargs ); if ( rc != 0 ) { Remove_Lock_File(); Sagan_Log(S_ERROR, "[%s, line %d] Error creating Perfmonitor thread [error: %d].", __FILE__, __LINE__, rc); } } /* Open sagan alert file */ Sagan_Open_Log_File(OPEN, ALERT_LOG); /**************************************************************************** * Display processor information as we load ****************************************************************************/ /* Sagan_Track_Clients processor ********************************************/ if ( config->sagan_track_clients_flag) { if ( config->pp_sagan_track_clients ) Sagan_Log(S_NORMAL, "Client Tracking Processor: %d minute(s)", config->pp_sagan_track_clients); Sagan_Track_Clients_Init(); Sagan_Load_Tracking_Cache(); } /* Sagan Blacklist IP processor *********************************************/ if ( config->blacklist_flag) { Sagan_Blacklist_Init(); Sagan_Blacklist_Load(); } /* Sagan Websense processor ************************************************/ #ifdef WITH_WEBSENSE if ( config->websense_flag ) { curl_global_init(CURL_GLOBAL_ALL); config->websense_last_time = atol(config->sagan_startutime); Sagan_Websense_Init(); Sagan_Log(S_NORMAL, ""); Sagan_Log(S_NORMAL, "Websense URL: %s", config->websense_url); Sagan_Log(S_NORMAL, "Websense Auth: %s", config->websense_auth); Sagan_Log(S_NORMAL, "Websense Device ID: %s", config->websense_device_id); Sagan_Log(S_NORMAL, "Websense Categories File: %s", config->websense_cat); Sagan_Log(S_NORMAL, "Websense Max Cache: %d", config->websense_max_cache); Sagan_Log(S_NORMAL, "Websense Cache Timeout: %d minutes.", config->websense_timeout / 60); Sagan_Log(S_NORMAL, "Websense loaded %d categories.", counters->websense_cat_count); } #endif /* Sagan Bro Intel processor *******************************************/ if ( config->brointel_flag ) { Sagan_Log(S_NORMAL, ""); Sagan_BroIntel_Init(); Sagan_BroIntel_Load_File(); Sagan_Log(S_NORMAL, "Bro Intel::ADDR Loaded: %d", counters->brointel_addr_count); Sagan_Log(S_NORMAL, "Bro Intel::DOMAIN Loaded: %d", counters->brointel_domain_count); Sagan_Log(S_NORMAL, "Bro Intel::FILE_HASH Loaded: %d", counters->brointel_file_hash_count); Sagan_Log(S_NORMAL, "Bro Intel::URL Loaded: %d", counters->brointel_url_count); Sagan_Log(S_NORMAL, "Bro Intel::SOFTWARE Loaded: %d", counters->brointel_software_count); Sagan_Log(S_NORMAL, "Bro Intel::EMAIL Loaded: %d", counters->brointel_email_count); Sagan_Log(S_NORMAL, "Bro Intel::USER_NAME Loaded: %d", counters->brointel_user_name_count); Sagan_Log(S_NORMAL, "Bro Intel::FILE_NAME Loaded: %d", counters->brointel_file_name_count); Sagan_Log(S_NORMAL, "Bro Intel::CERT_HASH Loaded: %d", counters->brointel_cert_hash_count); Sagan_Log(S_NORMAL, "Bro Intel Duplicates Detected: %d", counters->brointel_dups); } /*************************************************************************** * Output plugins ***************************************************************************/ #ifdef HAVE_LIBESMTP if ( config->sagan_esmtp_flag ) { Sagan_Log(S_NORMAL, ""); if ( config->min_email_priority ) Sagan_Log(S_NORMAL, "E-mail on priority %d or higher.", config->min_email_priority); Sagan_Log(S_NORMAL, "E-Mail will be sent from: %s", config->sagan_esmtp_from); Sagan_Log(S_NORMAL, "SMTP server is set to: %s", config->sagan_esmtp_server); } #endif #ifdef WITH_SNORTSAM if ( config->sagan_fwsam_flag ) { Sagan_Log(S_NORMAL, ""); Sagan_Log(S_NORMAL, "Snortsam output plug in enabled."); } #endif if ( config->sagan_external_output_flag ) { Sagan_Log(S_NORMAL, ""); Sagan_Log(S_NORMAL, "External program to be called: %s", config->sagan_extern); } /* Unified2 ****************************************************************/ #if defined(HAVE_DNET_H) || defined(HAVE_DUMBNET_H) if ( config->sagan_unified2_flag ) { Sagan_Log(S_NORMAL, ""); Sagan_Log(S_NORMAL, "Unified2 file: %s", config->unified2_filepath); Sagan_Log(S_NORMAL, "Unified2 limit: %dM", config->unified2_limit / 1024 / 1024 ); Unified2InitFile(); } #endif /*************************************************************************** * Non-Processor/Output option ***************************************************************************/ /* What to "ignore" ********************************************************/ if ( config->sagan_droplist_flag ) { Load_Ignore_List(); Sagan_Log(S_NORMAL, ""); Sagan_Log(S_NORMAL, "Loaded %d ignore/drop list item(s).", counters->droplist_count); } /*************************************************************************** * Continue with normal startup! ***************************************************************************/ Sagan_Log(S_NORMAL, ""); Sagan_Log(S_NORMAL, " ,-._,-. -*> Sagan! <*-"); Sagan_Log(S_NORMAL, " \\/)\"(\\/ Version %s", VERSION); Sagan_Log(S_NORMAL, " (_o_) Champ Clark III & The Quadrant InfoSec Team [quadrantsec.com]"); Sagan_Log(S_NORMAL, " / \\/) Copyright (C) 2009-2015 Quadrant Information Security, et al."); Sagan_Log(S_NORMAL, " (|| ||) Using PCRE version: %s", pcre_version()); Sagan_Log(S_NORMAL, " oo-oo Sagan is processing events....."); Sagan_Log(S_NORMAL, ""); /* Become a daemon if requested */ if ( daemonize ) { Sagan_Log(S_NORMAL, "Becoming a daemon!"); pid_t pid = 0; setsid(); pid = fork(); if (pid == 0) {} else { exit(0); } } /* Create the signal handlers thread _after_ the fork() so it can properly * handly signals - Champ Clark III - 06/13/2011 */ rc = pthread_create( &sig_thread, NULL, (void *)Sig_Handler, sigargs ); if ( rc != 0 ) { Remove_Lock_File(); Sagan_Log(S_ERROR, "[%s, line %d] Error creating signal handler thread. [error: %d]", __FILE__, __LINE__, rc); } /* We don't want the key_handler() if we're in daemon mode! */ if (!daemonize) { rc = pthread_create( &key_thread, NULL, (void *)key_handler, NULL ); if ( rc != 0 ) { Remove_Lock_File(); Sagan_Log(S_ERROR, "[%s, line %d] Error creating key_handler thread. [error: %d]", __FILE__, __LINE__, rc); } } /* We do this after forking so init scripts can complete */ /* Check lock file _after_ thread. If you don't it'll retreive the wrong pid * and incorrectly believe there is a stale lock file if --daemon */ checklockfile(); Sagan_Log(S_NORMAL, "Spawning %d Processor Threads.", config->max_processor_threads); for (i = 0; i < config->max_processor_threads; i++) { rc = pthread_create ( &processor_id[i], &thread_processor_attr, (void *)Sagan_Processor, NULL ); if ( rc != 0 ) { Remove_Lock_File(); Sagan_Log(S_ERROR, "Could not pthread_create() for I/O processors [error: %d]", rc); } } Sagan_Log(S_NORMAL, ""); if ( config->sagan_fifo_flag == 0 ) { Sagan_Log(S_NORMAL, "Attempting to open syslog FIFO (%s).", config->sagan_fifo); } else { Sagan_Log(S_NORMAL, "Attempting to open syslog FILE (%s).", config->sagan_fifo); } while(1) { FILE *fd; fd = fopen(config->sagan_fifo, "r"); if ( config->sagan_fifo_flag == 0 ) { Sagan_Log(S_NORMAL, "Successfully opened FIFO (%s).", config->sagan_fifo); } else { Sagan_Log(S_NORMAL, "Successfully opened FILE (%s) and processing events.....", config->sagan_fifo); } while(fd != NULL) { while(fgets(syslogstring, sizeof(syslogstring), fd) != NULL) { /* If the FIFO was in a error state, let user know the FIFO writer has resumed */ if ( fifoerr == 1 ) { Sagan_Log(S_NORMAL, "FIFO writer has restarted. Processing events."); fifoerr=0; } counters->sagantotal++; syslog_host = strtok_r(syslogstring, "|", &tok); /* If we're using DNS (and we shouldn't be!), we start DNS checks and lookups * here. We cache both good and bad lookups to not over load our DNS server(s). * The only way DNS cache can be cleared is to restart Sagan */ if (config->syslog_src_lookup ) { if ( inet_pton(AF_INET, syslog_host, &(sa.sin_addr)) == 0 ) /* Is inbound a valid IP? */ { dns_flag=0; for(i=0; i <= counters->dns_cache_count ; i++) /* Check cache first */ { if (!strcmp( dnscache[i].hostname, syslog_host)) { syslog_host = dnscache[i].src_ip; dns_flag=1; } } /* If entry was not found in cache, look it up */ if ( dns_flag == 0 ) { /* Do a DNS lookup */ strlcpy(src_dns_lookup, DNS_Lookup(syslog_host), sizeof(src_dns_lookup)); /* Invalid lookups get the config->sagan_host value */ if (src_dns_lookup[0] == '0' ) { strlcpy(src_dns_lookup, config->sagan_host, sizeof(src_dns_lookup)); counters->dns_miss_count++; } /* Add entry to DNS Cache */ dnscache = (_SaganDNSCache *) realloc(dnscache, (counters->dns_cache_count+1) * sizeof(_SaganDNSCache)); strlcpy(dnscache[counters->dns_cache_count].hostname, syslog_host, sizeof(dnscache[counters->dns_cache_count].hostname)); strlcpy(dnscache[counters->dns_cache_count].src_ip, src_dns_lookup, sizeof(dnscache[counters->dns_cache_count].src_ip)); counters->dns_cache_count++; syslog_host = src_dns_lookup; } } } else { /* We check to see if values from our FIFO are valid. If we aren't doing DNS related * stuff (above), we start basic check with the syslog_host */ if (syslog_host == NULL || inet_pton(AF_INET, syslog_host, &(sa.sin_addr)) == 0 ) { syslog_host = config->sagan_host; pthread_mutex_lock(&SaganMalformedCounter); counters->malformed_host++; pthread_mutex_unlock(&SaganMalformedCounter); if ( debug->debugmalformed ) { Sagan_Log(S_WARN, "Sagan received a malformed 'host' (replaced with %s)", config->sagan_host); } } } // if ( config->home_any == 1) { /* We know check the rest of the values */ syslog_facility=strtok_r(NULL, "|", &tok); if ( syslog_facility == NULL ) { syslog_facility = "SAGAN: FACILITY ERROR"; pthread_mutex_lock(&SaganMalformedCounter); counters->malformed_facility++; pthread_mutex_unlock(&SaganMalformedCounter); if ( debug->debugmalformed ) { Sagan_Log(S_WARN, "Sagan received a malformed 'facility'"); } } syslog_priority=strtok_r(NULL, "|", &tok); if ( syslog_priority == NULL ) { syslog_priority = "SAGAN: PRIORITY ERROR"; pthread_mutex_lock(&SaganMalformedCounter); counters->malformed_priority++; pthread_mutex_unlock(&SaganMalformedCounter); if ( debug->debugmalformed ) { Sagan_Log(S_WARN, "Sagan received a malformed 'priority'"); } } syslog_level=strtok_r(NULL, "|", &tok); if ( syslog_level == NULL ) { syslog_level = "SAGAN: LEVEL ERROR"; pthread_mutex_lock(&SaganMalformedCounter); counters->malformed_level++; pthread_mutex_unlock(&SaganMalformedCounter); if ( debug->debugmalformed ) { Sagan_Log(S_WARN, "Sagan received a malformed 'level'"); } } syslog_tag=strtok_r(NULL, "|", &tok); if ( syslog_tag == NULL ) { syslog_tag = "SAGAN: TAG ERROR"; pthread_mutex_lock(&SaganMalformedCounter); counters->malformed_tag++; pthread_mutex_unlock(&SaganMalformedCounter); if ( debug->debugmalformed ) { Sagan_Log(S_WARN, "Sagan received a malformed 'tag'"); } } syslog_date=strtok_r(NULL, "|", &tok); if ( syslog_date == NULL ) { syslog_date = "SAGAN: DATE ERROR"; pthread_mutex_lock(&SaganMalformedCounter); counters->malformed_date++; pthread_mutex_unlock(&SaganMalformedCounter); if ( debug->debugmalformed ) { Sagan_Log(S_WARN, "Sagan received a malformed 'date'"); } } syslog_time=strtok_r(NULL, "|", &tok); if ( syslog_time == NULL ) { syslog_time = "SAGAN: TIME ERROR"; pthread_mutex_lock(&SaganMalformedCounter); counters->malformed_time++; pthread_mutex_unlock(&SaganMalformedCounter); if ( debug->debugmalformed ) { Sagan_Log(S_WARN, "Sagan received a malformed 'time'"); } } syslog_program=strtok_r(NULL, "|", &tok); if ( syslog_program == NULL ) { syslog_program = "SAGAN: PROGRAM ERROR"; pthread_mutex_lock(&SaganMalformedCounter); counters->malformed_program++; pthread_mutex_unlock(&SaganMalformedCounter); if ( debug->debugmalformed ) { Sagan_Log(S_WARN, "Sagan received a malformed 'program'"); } } syslog_msg=strtok_r(NULL, "", &tok); /* In case the message has | in it, we delimit on "" */ if ( syslog_msg == NULL ) { syslog_msg = "SAGAN: MESSAGE ERROR"; pthread_mutex_lock(&SaganMalformedCounter); counters->malformed_message++; pthread_mutex_unlock(&SaganMalformedCounter); if ( debug->debugmalformed ) { Sagan_Log(S_WARN, "Sagan received a malformed 'message' [Syslog Host: %s]", syslog_host); } /* If the message is lost, all is lost. Typically, you don't lose part of the message, * it's more likely to lose all - Champ Clark III 11/17/2011 */ counters->sagan_log_drop++; } /* Strip any \n or \r from the syslog_msg */ if ( strcspn ( syslog_msg, "\n" ) < strlen(syslog_msg) ) syslog_msg[strcspn ( syslog_msg, "\n" )] = '\0'; if ( proc_msgslot < config->max_processor_threads ) { pthread_mutex_lock(&SaganProcWorkMutex); strlcpy(SaganProcSyslog[proc_msgslot].syslog_host, syslog_host, sizeof(SaganProcSyslog[proc_msgslot].syslog_host)); strlcpy(SaganProcSyslog[proc_msgslot].syslog_facility, syslog_facility, sizeof(SaganProcSyslog[proc_msgslot].syslog_facility)); strlcpy(SaganProcSyslog[proc_msgslot].syslog_priority, syslog_priority, sizeof(SaganProcSyslog[proc_msgslot].syslog_priority)); strlcpy(SaganProcSyslog[proc_msgslot].syslog_level, syslog_level, sizeof(SaganProcSyslog[proc_msgslot].syslog_level)); strlcpy(SaganProcSyslog[proc_msgslot].syslog_tag, syslog_tag, sizeof(SaganProcSyslog[proc_msgslot].syslog_tag)); strlcpy(SaganProcSyslog[proc_msgslot].syslog_date, syslog_date, sizeof(SaganProcSyslog[proc_msgslot].syslog_date)); strlcpy(SaganProcSyslog[proc_msgslot].syslog_time, syslog_time, sizeof(SaganProcSyslog[proc_msgslot].syslog_time)); strlcpy(SaganProcSyslog[proc_msgslot].syslog_program, syslog_program, sizeof(SaganProcSyslog[proc_msgslot].syslog_program)); strlcpy(SaganProcSyslog[proc_msgslot].syslog_message, syslog_msg, sizeof(SaganProcSyslog[proc_msgslot].syslog_message)); proc_msgslot++; pthread_cond_signal(&SaganProcDoWork); pthread_mutex_unlock(&SaganProcWorkMutex); } else { counters->worker_thread_exhaustion++; counters->sagan_log_drop++; } if (debug->debugthreads) Sagan_Log(S_DEBUG, "Current \"proc_msgslot\": %d", proc_msgslot); if (debug->debugsyslog) { Sagan_Log(S_DEBUG, "[%s, line %d] **[RAW Syslog]*********************************", __FILE__, __LINE__); Sagan_Log(S_DEBUG, "[%s, line %d] Host: %s | Program: %s | Facility: %s | Priority: %s | Level: %s | Tag: %s", __FILE__, __LINE__, syslog_host, syslog_program, syslog_facility, syslog_priority, syslog_level, syslog_tag); Sagan_Log(S_DEBUG, "[%s, line %d] Raw message: %s", __FILE__, __LINE__, syslog_msg); } } /* while(fgets) */ /* fgets() has returned a error, likely due to the FIFO writer leaving */ /* DEBUG : set a kill flag and join */ /* RMEOVE LOCK */ if ( fifoerr == 0 ) { if ( config->sagan_fifo_flag != 0 ) { Sagan_Log(S_NORMAL, "EOF reached. Waiting for threads to catch up"); sleep(5); fclose(fd); Sagan_Log(S_NORMAL, "Exiting."); /* DEBUG: Rejoin threads */ exit(0); } else { Sagan_Log(S_WARN, "FIFO writer closed. Waiting for FIFO writer to restart...."); fifoerr=1; /* Set flag so our wile(fgets) knows */ } } sleep(1); /* So we don't eat 100% CPU */ } /* while(fd != NULL) */ fclose(fd); /* ???? */ } /* End of while(1) */ } /* End of main */
bool AtlasResourceCompiler::Compile() { Platform* platform = Platform::Get(); // Load configuration if we haven't already. if (m_config_file == NULL) { if (!Load_Config()) { return false; } } // Compile time. DBG_LOG("Compiling atlas resource '%s'.", m_input_path.c_str()); // Create new atlas, and start adding rectangles. Atlas* atlas = new Atlas(m_config_file); atlas->Lock_Textures(); // Add each of the source-images. std::vector<ConfigFileNode> images = m_config_file->Get<std::vector<ConfigFileNode>>("images/image"); for (std::vector<ConfigFileNode>::iterator iter = images.begin(); iter != images.end(); iter++) { ConfigFileNode node = *iter; const char* type = m_config_file->Get<const char*>("type", node, true); const char* file = m_config_file->Get<const char*>("file", node, true); Point origin = Point(0, 0); if (m_config_file->Contains("origin", node, true)) { origin = m_config_file->Get<Point>("origin", node, true); } if (stricmp(type, "single") == 0) { const char* name = m_config_file->Get<const char*>("name", node, true); Texture* texture = TextureFactory::Load_Without_Handle(file, TextureFlags::None); DBG_ASSERT_STR(texture != NULL, "Could not load dependent texture '%s'.", file); atlas->Add_Frame(name, texture, Rect(0, 0, texture->Get_Width(), texture->Get_Height()), origin); } else if (stricmp(type, "multiple") == 0) { const char* name = m_config_file->Get<const char*>("name", node, true); // Grab all the file paths. std::string name_str = name; std::vector<std::string> files; Expand_Multiple_Path(file, files); // Grab hash mark. int hash_mark = name_str.find('#'); DBG_ASSERT_STR(hash_mark != std::string::npos, "Image marked as type 'multiple' does not contain replacement hash mark."); std::string split_left = name_str.substr(0, hash_mark); std::string split_right = name_str.substr(hash_mark + 1); // Add each file. int counter = 0; for (std::vector<std::string>::iterator subiter = files.begin(); subiter != files.end(); subiter++) { std::string sub_path = *subiter; std::string sub_name = split_left + StringHelper::To_String(counter++) + split_right; Texture* texture = TextureFactory::Load_Without_Handle(sub_path.c_str(), TextureFlags::None); DBG_ASSERT_STR(texture != NULL, "Could not load dependent texture '%s'.", sub_path); atlas->Add_Frame(sub_name.c_str(), texture, Rect(0, 0, texture->Get_Width(), texture->Get_Height()), origin); } } else if (stricmp(type, "grid") == 0) { const char* name = m_config_file->Get<const char*>("name", node, true); Texture* texture = TextureFactory::Load_Without_Handle(file, TextureFlags::None); DBG_ASSERT_STR(texture != NULL, "Could not load dependent texture '%s'.", file); // Grab hash mark. std::string name_str = name; int hash_mark = name_str.find('#'); DBG_ASSERT_STR(hash_mark != std::string::npos, "Image marked as type 'grid' does not contain replacement hash mark."); std::string split_left = name_str.substr(0, hash_mark); std::string split_right = name_str.substr(hash_mark + 1); // Iterate over each sub-image. int frame_width = m_config_file->Get<int>("width", node, true); int frame_height = m_config_file->Get<int>("height", node, true); int frame_hspace = m_config_file->Get<int>("hspace", node, true); int frame_vspace = m_config_file->Get<int>("vspace", node, true); float texture_width = (float)texture->Get_Width(); float texture_height = (float)texture->Get_Height(); int cell_count_u = texture_width / (frame_width + frame_hspace); int cell_count_v = texture_height / (frame_height + frame_vspace); int cell_count = cell_count_u * cell_count_v; for (int i = 0; i < cell_count; i++) { int u = i % cell_count_u; int v = i / cell_count_u; int u_offset = floor(u * (frame_width + frame_hspace)); int v_offset = floor(v * (frame_height + frame_vspace)); std::string sub_name = split_left + StringHelper::To_String(i) + split_right; atlas->Add_Frame(sub_name.c_str(), texture, Rect(u_offset, v_offset, frame_width, frame_height), origin); } } else if (stricmp(type, "atlas") == 0) { Texture* texture = TextureFactory::Load_Without_Handle(file, TextureFlags::None); DBG_ASSERT_STR(texture != NULL, "Could not load dependent texture '%s'.", file); // Calculate frame positions for atlas. int frame_width = m_config_file->Get<int>("width", node, true); int frame_height = m_config_file->Get<int>("height", node, true); int frame_hspace = m_config_file->Get<int>("hspace", node, true); int frame_vspace = m_config_file->Get<int>("vspace", node, true); float texture_width = (float)texture->Get_Width(); float texture_height = (float)texture->Get_Height(); int cell_count_u = texture_width / (frame_width + frame_hspace); int cell_count_v = texture_height / (frame_height + frame_vspace); int cell_count = cell_count_u * cell_count_v; // Iterate over each sub-image. std::vector<ConfigFileNode> sub_images = m_config_file->Get<std::vector<ConfigFileNode>>("subimage", node); for (std::vector<ConfigFileNode>::iterator subiter = sub_images.begin(); subiter != sub_images.end(); subiter++) { ConfigFileNode sub_node = *subiter; const char* sub_type = m_config_file->Get<const char*>("type", sub_node, true); const char* sub_name = m_config_file->Get<const char*>("name", sub_node, true); if (stricmp(sub_type, "single") == 0) { int frame = m_config_file->Get<int>("frame", sub_node, true); int u = frame % cell_count_u; int v = frame / cell_count_u; int u_offset = floor(u * (frame_width + frame_hspace)); int v_offset = floor(v * (frame_height + frame_vspace)); atlas->Add_Frame(sub_name, texture, Rect(u_offset, v_offset, frame_width, frame_height), origin); } else if (stricmp(sub_type, "strip") == 0) { int to_frame = m_config_file->Get<int>("to_frame", sub_node, true); int from_frame = m_config_file->Get<int>("from_frame", sub_node, true); DBG_ASSERT_STR(to_frame >= from_frame, "Invalid strip range %i to %i.", from_frame, to_frame); std::string sub_name_str = sub_name; int hash_mark = sub_name_str.find('#'); DBG_ASSERT_STR(hash_mark != std::string::npos, "Sub-image marked as type 'strip' does not contain replacement hash mark."); std::string split_left = sub_name_str.substr(0, hash_mark); std::string split_right = sub_name_str.substr(hash_mark + 1); for(int frame = from_frame; frame <= to_frame; frame++) { int u = frame % cell_count_u; int v = frame / cell_count_u; int u_offset = floor(u * (frame_width + frame_hspace)); int v_offset = floor(v * (frame_height + frame_vspace)); std::string sub_sub_name = split_left + StringHelper::To_String(frame) + split_right; atlas->Add_Frame(sub_sub_name.c_str(), texture, Rect(u_offset, v_offset, frame_width, frame_height), origin); } } else { DBG_ASSERT_STR(false, "Unknown or invalid sub-image type '%s'", sub_type); } } } else { DBG_ASSERT_STR(false, "Unknown or invalid source-image type '%s'", type); } } // Add each of the animations. std::vector<ConfigFileNode> animations = m_config_file->Get<std::vector<ConfigFileNode>>("animations/animation"); for (std::vector<ConfigFileNode>::iterator iter = animations.begin(); iter != animations.end(); iter++) { ConfigFileNode node = *iter; const char* name = m_config_file->Get<const char*>("name", node, true); const char* mode = m_config_file->Get<const char*>("mode", node, true); float speed = m_config_file->Get<float>("speed", node, true); std::vector<AtlasFrame*> out_frames; // Decode the animation mode. AtlasAnimationMode::Type anim_mode; if (stricmp(mode, "once") == 0) { anim_mode = AtlasAnimationMode::Once; } else if (stricmp(mode, "loop") == 0) { anim_mode = AtlasAnimationMode::Loop; } else { DBG_ASSERT_STR(false, "Unknown or invalid animation mode '%s'", mode); } // Work out the names of each of the frames. std::vector<ConfigFileNode> frames = m_config_file->Get<std::vector<ConfigFileNode>>("frame", node); for (std::vector<ConfigFileNode>::iterator frameiter = frames.begin(); frameiter != frames.end(); frameiter++) { ConfigFileNode frame_node = *frameiter; const char* frame_type = m_config_file->Get<const char*>("type", frame_node, true); const char* frame_name = m_config_file->Get<const char*>("name", frame_node, true); if (stricmp(frame_type, "single") == 0) { AtlasFrame* frame = atlas->Get_Frame(frame_name); DBG_ASSERT(frame != NULL, "Invalid frame name '%s' in animation '%s'.", frame_name, name); out_frames.push_back(frame); } else if (stricmp(frame_type, "multiple") == 0) { LinkedList<AtlasFrame*>& frames = atlas->Get_Frames_List(); std::string name_str = frame_name; int hash_mark = name_str.find('#'); DBG_ASSERT_STR(hash_mark != std::string::npos, "Animation marked as type 'multiple' does not contain replacement hash mark."); std::string split_left = name_str.substr(0, hash_mark); std::string split_right = name_str.substr(hash_mark + 1); for (LinkedList<AtlasFrame*>::Iterator animiter = frames.Begin(); animiter != frames.End(); animiter++) { AtlasFrame* anim = *animiter; if (anim->Name.size() > split_left.size() + split_right.size()) { if (anim->Name.substr(0, split_left.size()) == split_left && anim->Name.substr((anim->Name.size() - split_right.size()), split_right.size()) == split_right) { AtlasFrame* frame = atlas->Get_Frame(anim->Name.c_str()); DBG_ASSERT(frame != NULL, "Invalid frame name '%s' in animation '%s'.", anim->Name, name); out_frames.push_back(frame); } } } } else { DBG_ASSERT_STR(false, "Unknown or invalid frame type '%s'", frame_type); } } // Add the animation. atlas->Add_Animation(name, speed, anim_mode, out_frames); } // Save compiled file. atlas->Unlock_Textures(); // Configuration settings. ConfigFile config; // Store configuration settings. config.Set<const char*>("settings/texture-size", m_config_file->Get<const char*>("settings/texture-size")); config.Set<const char*>("settings/max-textures", m_config_file->Get<const char*>("settings/max-textures")); // Save pngs. int texture_count = 0; AtlasTexture** textures = atlas->Get_Textures(texture_count); for (int i = 0; i < texture_count; i++) { AtlasTexture* texture = textures[i]; std::string output_path = (m_output_path + "." + StringHelper::To_String(i) + ".png"); // Save texture file. TextureFactory::Save(output_path.c_str(), texture->Texture, TextureFlags::None); // Store texture spec in xml. ConfigFileNode node = config.New_Node("textures/texture"); config.Set(NULL, output_path.c_str(), node, false); } // Save frame configuration. config.New_Node("frames"); HashTable<AtlasFrame*, unsigned int>& frames = atlas->Get_Frames(); for (HashTable<AtlasFrame*, unsigned int>::Iterator iter = frames.Begin(); iter != frames.End(); iter++) { AtlasFrame* frame = iter.Get_Value(); // Store character spec in xml. ConfigFileNode node = config.New_Node("frames/frame"); config.Set("name", frame->Name.c_str(), node, true); config.Set("namehash", frame->NameHash, node, true); config.Set("texture", frame->TextureIndex, node, true); config.Set("rectangle", frame->Rectangle, node, true); config.Set("uv", frame->UV, node, true); config.Set("origin", frame->Origin, node, true); } // Save animation configuration. config.New_Node("animations"); HashTable<AtlasAnimation*, unsigned int>& anims = atlas->Get_Animations(); for (HashTable<AtlasAnimation*, unsigned int>::Iterator iter = anims.Begin(); iter != anims.End(); iter++) { AtlasAnimation* frame = iter.Get_Value(); // Store character spec in xml. ConfigFileNode node = config.New_Node("animations/animation"); config.Set("name", frame->Name.c_str(), node, true); config.Set("namehash", frame->NameHash, node, true); switch (frame->Mode) { case AtlasAnimationMode::Loop: config.Set("mode", "loop", node, true); break; case AtlasAnimationMode::Once: config.Set("mode", "once", node, true); break; default: DBG_ASSERT_STR(false, "Invalid animation mode."); } config.Set("speed", frame->Speed, node, true); for (std::vector<AtlasFrame*>::iterator iter = frame->Frames.begin(); iter != frame->Frames.end(); iter++) { AtlasFrame* frame = (*iter); ConfigFileNode subnode = config.New_Node("frame", node); config.Set("name", frame->Name.c_str(), subnode, true); config.Set("namehash", frame->NameHash, subnode, true); } } // Save font xml configuration. config.Save(m_output_path.c_str()); // Update timestamps. Update_File_Timestamp(m_input_path); // Update timestamps on dependent files. for (std::vector<std::string>::iterator iter = m_dependent_files.begin(); iter != m_dependent_files.end(); iter++) { std::string path = (*iter); DBG_ASSERT_STR(Platform::Get()->Is_File(path.c_str()), "Could not find dependent file '%s'.", path.c_str()); Update_File_Timestamp(path.c_str()); } DBG_LOG("Finished compiling to '%s'.", m_output_path.c_str()); return true; }
void Sig_Handler( _SaganSigArgs *args ) { sigset_t signal_set; int sig; sbool orig_perfmon_value = 0; #ifdef HAVE_LIBPCAP sbool orig_plog_value = 0; #endif for(;;) { /* wait for any and all signals */ sigfillset( &signal_set ); sigwait( &signal_set, &sig ); switch( sig ) { /* exit */ case SIGQUIT: case SIGINT: case SIGTERM: case SIGSEGV: case SIGABRT: Sagan_Log(S_NORMAL, "\n\n[Received signal %d. Sagan version %s shutting down]-------\n", sig, VERSION); Sagan_Statistics(); #if defined(HAVE_DNET_H) || defined(HAVE_DUMBNET_H) if ( sagan_unified2_flag ) { Unified2CleanExit(); } #endif #ifdef HAVE_LIBMAXMINDDB MMDB_close(&config->geoip2); #endif fflush(config->sagan_alert_stream); fclose(config->sagan_alert_stream); /* Close Sagan alert file */ fflush(config->sagan_log_stream); /* Close the sagan.log */ fclose(config->sagan_log_stream); if ( config->perfmonitor_flag ) { Sagan_Perfmonitor_Close(); } Remove_Lock_File(); exit(0); break; case SIGHUP: config->sagan_reload = 1; /* Only this thread can alter this */ pthread_mutex_lock(&SaganReloadMutex); Sagan_Log(S_NORMAL, "[Reloading Sagan version %s.]-------", VERSION); /* * Close and re-open log files. This is for logrotate and such * 04/14/2015 - Champ Clark III ([email protected]) */ Sagan_Open_Log_File(REOPEN, ALL_LOGS); /******************/ /* Reset counters */ /******************/ counters->refcount=0; counters->classcount=0; counters->rulecount=0; counters->ruletotal=0; counters->genmapcount=0; counters->flowbit_track_count=0; memset(rulestruct, 0, sizeof(_Rule_Struct)); memset(classstruct, 0, sizeof(_Class_Struct)); memset(generator, 0, sizeof(_Sagan_Processor_Generator)); memset(flowbit, 0, sizeof(_Sagan_Flowbit)); /**********************************/ /* Disabled and reset processors. */ /**********************************/ /* Note: Processors that run as there own thread (perfmon, plog) cannot be * loaded via SIGHUP. They must be loaded at run time. Once they are loaded, * they can be disabled/re-enabled. */ /* Single Threaded processors */ if ( config->perfmonitor_flag == 1 && orig_perfmon_value == 0 ) { Sagan_Perfmonitor_Close(); orig_perfmon_value = 1; } config->perfmonitor_flag = 0; #ifdef HAVE_LIBPCAP if ( config->plog_flag ) { orig_plog_value = 1; } config->plog_flag = 0; #endif /* Multi Threaded processors */ config->blacklist_flag = 0; if ( config->blacklist_flag ) { free(SaganBlacklist); } config->blacklist_flag = 0; if ( config->brointel_flag ) { free(Sagan_BroIntel_Intel_Addr); free(Sagan_BroIntel_Intel_Domain); free(Sagan_BroIntel_Intel_File_Hash); free(Sagan_BroIntel_Intel_URL); free(Sagan_BroIntel_Intel_Software); free(Sagan_BroIntel_Intel_Email); free(Sagan_BroIntel_Intel_User_Name); free(Sagan_BroIntel_Intel_File_Name); free(Sagan_BroIntel_Intel_Cert_Hash); counters->brointel_addr_count = 0; counters->brointel_domain_count = 0; counters->brointel_file_hash_count = 0; counters->brointel_url_count = 0; counters->brointel_software_count = 0; counters->brointel_email_count = 0; counters->brointel_user_name_count = 0; counters->brointel_file_name_count = 0; counters->brointel_cert_hash_count = 0; counters->brointel_dups = 0; } config->brointel_flag = 0; if ( config->sagan_track_clients_flag ) { free(SaganTrackClients); fclose(config->sagan_track_client_file); } config->sagan_track_clients_flag = 0; counters->track_clients_client_count = 0; counters->track_clients_down = 0; /* Output formats */ config->sagan_ext_flag = 0; #ifdef WITH_SYSLOG config->sagan_syslog_flag = 0; #endif #ifdef HAVE_LIBESMTP config->sagan_esmtp_flag = 0; #endif #ifdef WITH_SNORTSAM config->sagan_fwsam_flag = 0; #endif /* Non-output / Processors */ if ( config->sagan_droplist_flag ) { config->sagan_droplist_flag = 0; free(SaganIgnorelist); } /************************************************************/ /* Re-load primary configuration (rules/classifictions/etc) */ /************************************************************/ Load_Config(); /* <- RELOAD */ /************************************************************/ /* Re-load primary configuration (rules/classifictions/etc) */ /************************************************************/ if ( config->perfmonitor_flag == 1 ) { if ( orig_perfmon_value == 1 ) { Sagan_Perfmonitor_Open(); } else { Sagan_Log(S_WARN, "** 'perfmonitor' must be loaded at runtime! NOT loading 'perfmonitor'!"); config->perfmonitor_flag = 0; } } #ifdef HAVE_LIBPCAP if ( config->plog_flag == 1 ) { if ( orig_plog_value == 1 ) { config->plog_flag = 1; } else { Sagan_Log(S_WARN, "** 'plog' must be loaded at runtime! NOT loading 'plog'!"); config->plog_flag = 0; } } #endif /* Load Blacklist data */ if ( config->blacklist_flag ) { counters->blacklist_count=0; Sagan_Blacklist_Init(); Sagan_Blacklist_Load(); } if ( config->brointel_flag ) { Sagan_BroIntel_Init(); Sagan_BroIntel_Load_File(); } if ( config->sagan_track_clients_flag ) { Sagan_Load_Tracking_Cache(); Sagan_Log(S_NORMAL, "Reset Sagan Track Client."); } /* Non output / processors */ if ( config->sagan_droplist_flag ) { Load_Ignore_List(); Sagan_Log(S_NORMAL, "Loaded %d ignore/drop list item(s).", counters->droplist_count); } #ifdef HAVE_LIBMAXMINDDB Sagan_Log(S_NORMAL, "Reloading GeoIP2 data."); Sagan_Open_GeoIP2_Database(); #endif #ifdef HAVE_LIBLOGNORM Sagan_Liblognorm_Load(); #endif pthread_cond_signal(&SaganReloadCond); pthread_mutex_unlock(&SaganReloadMutex); config->sagan_reload = 0; Sagan_Log(S_NORMAL, "Configuration reloaded."); break; /* Signals to ignore */ case 17: /* Child process has exited. */ case 28: /* Terminal 'resize'/alarm. */ break; case SIGUSR1: Sagan_Statistics(); break; default: Sagan_Log(S_NORMAL, "[Received signal %d. Sagan doesn't know how to deal with]", sig); } } }