/** * \brief Create a new LogFileCtx for "fast" output style. * \param conf The configuration node for this output. * \return A LogFileCtx pointer on success, NULL on failure. */ static OutputCtx *JsonAlertLogInitCtxSub(ConfNode *conf, OutputCtx *parent_ctx) { AlertJsonThread *ajt = parent_ctx->data; OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) return NULL; if (conf) { const char *payload = ConfNodeLookupChildValue(conf, "payload"); const char *packet = ConfNodeLookupChildValue(conf, "packet"); const char *payload_printable = ConfNodeLookupChildValue(conf, "payload-printable"); if (payload_printable != NULL) { if (ConfValIsTrue(payload_printable)) { ajt->file_ctx->flags |= LOG_JSON_PAYLOAD; } } if (payload != NULL) { if (ConfValIsTrue(payload)) { ajt->file_ctx->flags |= LOG_JSON_PAYLOAD_BASE64; } } if (packet != NULL) { if (ConfValIsTrue(packet)) { ajt->file_ctx->flags |= LOG_JSON_PACKET; } } } output_ctx->data = ajt->file_ctx; output_ctx->DeInit = JsonAlertLogDeInitCtxSub; return output_ctx; }
/** \brief Create a new http log LogFileCtx. * \param conf Pointer to ConfNode containing this loggers configuration. * \return NULL if failure, LogFileCtx* to the file_ctx if succesful * */ OutputCtx *LogStatsLogInitCtx(ConfNode *conf) { LogFileCtx *file_ctx = LogFileNewCtx(); if (file_ctx == NULL) { SCLogError(SC_ERR_HTTP_LOG_GENERIC, "couldn't create new file_ctx"); return NULL; } if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { LogFileFreeCtx(file_ctx); return NULL; } LogStatsFileCtx *statslog_ctx = SCMalloc(sizeof(LogStatsFileCtx)); if (unlikely(statslog_ctx == NULL)) { LogFileFreeCtx(file_ctx); return NULL; } memset(statslog_ctx, 0x00, sizeof(LogStatsFileCtx)); statslog_ctx->flags = LOG_STATS_TOTALS; if (conf != NULL) { const char *totals = ConfNodeLookupChildValue(conf, "totals"); const char *threads = ConfNodeLookupChildValue(conf, "threads"); const char *nulls = ConfNodeLookupChildValue(conf, "null-values"); SCLogDebug("totals %s threads %s", totals, threads); if (totals != NULL && ConfValIsFalse(totals)) { statslog_ctx->flags &= ~LOG_STATS_TOTALS; } if (threads != NULL && ConfValIsTrue(threads)) { statslog_ctx->flags |= LOG_STATS_THREADS; } if (nulls != NULL && ConfValIsTrue(nulls)) { statslog_ctx->flags |= LOG_STATS_NULLS; } SCLogDebug("statslog_ctx->flags %08x", statslog_ctx->flags); } statslog_ctx->file_ctx = file_ctx; OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { LogFileFreeCtx(file_ctx); SCFree(statslog_ctx); return NULL; } output_ctx->data = statslog_ctx; output_ctx->DeInit = LogStatsLogDeInitCtx; SCLogDebug("STATS log output initialized"); return output_ctx; }
/** \brief Create a new http log LogFilestoreCtx. * \param conf Pointer to ConfNode containing this loggers configuration. * \return NULL if failure, LogFilestoreCtx* to the file_ctx if succesful * */ static OutputCtx *LogFilestoreLogInitCtx(ConfNode *conf) { LogFileCtx *logfile_ctx = LogFileNewCtx(); if (logfile_ctx == NULL) { SCLogDebug("Could not create new LogFilestoreCtx"); return NULL; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) return NULL; output_ctx->data = NULL; output_ctx->DeInit = LogFilestoreLogDeInitCtx; char *s_default_log_dir = NULL; s_default_log_dir = ConfigGetLogDirectory(); const char *s_base_dir = NULL; s_base_dir = ConfNodeLookupChildValue(conf, "log-dir"); if (s_base_dir == NULL || strlen(s_base_dir) == 0) { strlcpy(g_logfile_base_dir, s_default_log_dir, sizeof(g_logfile_base_dir)); } else { if (PathIsAbsolute(s_base_dir)) { strlcpy(g_logfile_base_dir, s_base_dir, sizeof(g_logfile_base_dir)); } else { snprintf(g_logfile_base_dir, sizeof(g_logfile_base_dir), "%s/%s", s_default_log_dir, s_base_dir); } } const char *force_magic = ConfNodeLookupChildValue(conf, "force-magic"); if (force_magic != NULL && ConfValIsTrue(force_magic)) { FileForceMagicEnable(); SCLogInfo("forcing magic lookup for stored files"); } const char *force_md5 = ConfNodeLookupChildValue(conf, "force-md5"); if (force_md5 != NULL && ConfValIsTrue(force_md5)) { #ifdef HAVE_NSS FileForceMd5Enable(); SCLogInfo("forcing md5 calculation for stored files"); #else SCLogInfo("md5 calculation requires linking against libnss"); #endif } SCLogInfo("storing files in %s", g_logfile_base_dir); SCReturnPtr(output_ctx, "OutputCtx"); }
OutputCtx *OutputStatsLogInit(ConfNode *conf) { LogFileCtx *file_ctx = LogFileNewCtx(); if(file_ctx == NULL) { SCLogError(SC_ERR_STATS_LOG_GENERIC, "couldn't create new file_ctx"); return NULL; } if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { LogFileFreeCtx(file_ctx); return NULL; } OutputStatsCtx *stats_ctx = SCMalloc(sizeof(OutputStatsCtx)); if (unlikely(stats_ctx == NULL)) { LogFileFreeCtx(file_ctx); return NULL; } stats_ctx->flags = JSON_STATS_TOTALS; if (conf != NULL) { const char *totals = ConfNodeLookupChildValue(conf, "totals"); const char *threads = ConfNodeLookupChildValue(conf, "threads"); const char *deltas = ConfNodeLookupChildValue(conf, "deltas"); SCLogDebug("totals %s threads %s deltas %s", totals, threads, deltas); if (totals != NULL && ConfValIsFalse(totals)) { stats_ctx->flags &= ~JSON_STATS_TOTALS; } if (threads != NULL && ConfValIsTrue(threads)) { stats_ctx->flags |= JSON_STATS_THREADS; } if (deltas != NULL && ConfValIsTrue(deltas)) { stats_ctx->flags |= JSON_STATS_DELTAS; } SCLogDebug("stats_ctx->flags %08x", stats_ctx->flags); } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { LogFileFreeCtx(file_ctx); SCFree(stats_ctx); return NULL; } stats_ctx->file_ctx = file_ctx; output_ctx->data = stats_ctx; output_ctx->DeInit = OutputStatsLogDeinit; return output_ctx; }
OutputCtx *OutputStatsLogInitSub(ConfNode *conf, OutputCtx *parent_ctx) { AlertJsonThread *ajt = parent_ctx->data; OutputStatsCtx *stats_ctx = SCMalloc(sizeof(OutputStatsCtx)); if (unlikely(stats_ctx == NULL)) return NULL; stats_ctx->flags = JSON_STATS_TOTALS; if (conf != NULL) { const char *totals = ConfNodeLookupChildValue(conf, "totals"); const char *threads = ConfNodeLookupChildValue(conf, "threads"); const char *deltas = ConfNodeLookupChildValue(conf, "deltas"); SCLogDebug("totals %s threads %s deltas %s", totals, threads, deltas); if ((totals != NULL && ConfValIsFalse(totals)) && (threads != NULL && ConfValIsFalse(threads))) { SCFree(stats_ctx); SCLogError(SC_ERR_JSON_STATS_LOG_NEGATED, "Cannot disable both totals and threads in stats logging"); return NULL; } if (totals != NULL && ConfValIsFalse(totals)) { stats_ctx->flags &= ~JSON_STATS_TOTALS; } if (threads != NULL && ConfValIsTrue(threads)) { stats_ctx->flags |= JSON_STATS_THREADS; } if (deltas != NULL && ConfValIsTrue(deltas)) { stats_ctx->flags |= JSON_STATS_DELTAS; } SCLogDebug("stats_ctx->flags %08x", stats_ctx->flags); } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { SCFree(stats_ctx); return NULL; } stats_ctx->file_ctx = ajt->file_ctx; output_ctx->data = stats_ctx; output_ctx->DeInit = OutputStatsLogDeinitSub; return output_ctx; }
void SCProfilingKeywordsGlobalInit(void) { ConfNode *conf; conf = ConfGetNode("profiling.keywords"); if (conf != NULL) { if (ConfNodeChildValueIsTrue(conf, "enabled")) { profiling_keyword_enabled = 1; const char *filename = ConfNodeLookupChildValue(conf, "filename"); if (filename != NULL) { char *log_dir; log_dir = ConfigGetLogDirectory(); profiling_file_name = SCMalloc(PATH_MAX); if (unlikely(profiling_file_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "can't duplicate file name"); exit(EXIT_FAILURE); } snprintf(profiling_file_name, PATH_MAX, "%s/%s", log_dir, filename); const char *v = ConfNodeLookupChildValue(conf, "append"); if (v == NULL || ConfValIsTrue(v)) { profiling_file_mode = "a"; } else { profiling_file_mode = "w"; } profiling_keywords_output_to_file = 1; } } } }
static OutputCtx *JsonDropLogInitCtxSub(ConfNode *conf, OutputCtx *parent_ctx) { if (OutputDropLoggerEnable() != 0) { SCLogError(SC_ERR_CONF_YAML_ERROR, "only one 'drop' logger " "can be enabled"); return NULL; } AlertJsonThread *ajt = parent_ctx->data; JsonDropOutputCtx *drop_ctx = SCCalloc(1, sizeof(*drop_ctx)); if (drop_ctx == NULL) return NULL; OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { JsonDropOutputCtxFree(drop_ctx); return NULL; } if (conf) { const char *extended = ConfNodeLookupChildValue(conf, "alerts"); if (extended != NULL) { if (ConfValIsTrue(extended)) { drop_ctx->flags = LOG_DROP_ALERTS; } } } drop_ctx->file_ctx = ajt->file_ctx; output_ctx->data = drop_ctx; output_ctx->DeInit = JsonDropLogDeInitCtxSub; return output_ctx; }
OutputCtx *OutputTlsLogInitSub(ConfNode *conf, OutputCtx *parent_ctx) { OutputJsonCtx *ojc = parent_ctx->data; OutputTlsCtx *tls_ctx = SCMalloc(sizeof(OutputTlsCtx)); if (unlikely(tls_ctx == NULL)) return NULL; OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { SCFree(tls_ctx); return NULL; } tls_ctx->file_ctx = ojc->file_ctx; tls_ctx->flags = LOG_TLS_DEFAULT; if (conf) { const char *extended = ConfNodeLookupChildValue(conf, "extended"); if (extended != NULL) { if (ConfValIsTrue(extended)) { tls_ctx->flags = LOG_TLS_EXTENDED; } } } output_ctx->data = tls_ctx; output_ctx->DeInit = OutputTlsLogDeinitSub; AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_TLS); return output_ctx; }
OutputCtx *OutputHttpLogInitSub(ConfNode *conf, OutputCtx *parent_ctx) { AlertJsonThread *ajt = parent_ctx->data; LogHttpFileCtx *http_ctx = SCMalloc(sizeof(LogHttpFileCtx)); if (unlikely(http_ctx == NULL)) return NULL; OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { SCFree(http_ctx); return NULL; } http_ctx->file_ctx = ajt->file_ctx; http_ctx->flags = LOG_HTTP_DEFAULT; if (conf) { const char *extended = ConfNodeLookupChildValue(conf, "extended"); if (extended != NULL) { if (ConfValIsTrue(extended)) { http_ctx->flags = LOG_HTTP_EXTENDED; } } } output_ctx->data = http_ctx; output_ctx->DeInit = NULL; /* enable the logger for the app layer */ AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_HTTP); return output_ctx; }
int AppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name) { SCEnter(); int enabled = 1; char param[100]; ConfNode *node; int r; if (RunmodeIsUnittests()) goto enabled; r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.", alproto_name, ".enabled"); if (r < 0) { SCLogError(SC_ERR_FATAL, "snprintf failure."); exit(EXIT_FAILURE); } else if (r > (int)sizeof(param)) { SCLogError(SC_ERR_FATAL, "buffer not big enough to write param."); exit(EXIT_FAILURE); } node = ConfGetNode(param); if (node == NULL) { SCLogDebug("Entry for %s not found.", param); r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.", alproto_name, ".", ipproto, ".enabled"); if (r < 0) { SCLogError(SC_ERR_FATAL, "snprintf failure."); exit(EXIT_FAILURE); } else if (r > (int)sizeof(param)) { SCLogError(SC_ERR_FATAL, "buffer not big enough to write param."); exit(EXIT_FAILURE); } node = ConfGetNode(param); if (node == NULL) { SCLogDebug("Entry for %s not found.", param); goto enabled; } } if (ConfValIsTrue(node->val)) { goto enabled; } else if (ConfValIsFalse(node->val)) { goto disabled; } else if (strcasecmp(node->val, "detection-only") == 0) { goto disabled; } else { SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param); exit(EXIT_FAILURE); } disabled: enabled = 0; enabled: SCReturnInt(enabled); }
/** \brief Create a new http log LogFileCtx. * \param conf Pointer to ConfNode containing this loggers configuration. * \return NULL if failure, LogFileCtx* to the file_ctx if succesful * */ OutputCtx *OutputFileLogInitSub(ConfNode *conf, OutputCtx *parent_ctx) { OutputJsonCtx *ojc = parent_ctx->data; OutputFileCtx *output_file_ctx = SCMalloc(sizeof(OutputFileCtx)); if (unlikely(output_file_ctx == NULL)) return NULL; OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { SCFree(output_file_ctx); return NULL; } output_file_ctx->file_ctx = ojc->file_ctx; if (conf) { const char *force_filestore = ConfNodeLookupChildValue(conf, "force-filestore"); if (force_filestore != NULL && ConfValIsTrue(force_filestore)) { FileForceFilestoreEnable(); SCLogInfo("forcing filestore of all files"); } const char *force_magic = ConfNodeLookupChildValue(conf, "force-magic"); if (force_magic != NULL && ConfValIsTrue(force_magic)) { FileForceMagicEnable(); SCLogInfo("forcing magic lookup for logged files"); } const char *force_md5 = ConfNodeLookupChildValue(conf, "force-md5"); if (force_md5 != NULL && ConfValIsTrue(force_md5)) { #ifdef HAVE_NSS FileForceMd5Enable(); SCLogInfo("forcing md5 calculation for logged files"); #else SCLogInfo("md5 calculation requires linking against libnss"); #endif } } output_ctx->data = output_file_ctx; output_ctx->DeInit = OutputFileLogDeinitSub; FileForceTrackingEnable(); return output_ctx; }
/** \brief Create a new http log LogFileCtx. * \param conf Pointer to ConfNode containing this loggers configuration. * \return NULL if failure, LogFileCtx* to the file_ctx if succesful * */ static OutputCtx *LogFileLogInitCtx(ConfNode *conf) { LogFileCtx *logfile_ctx = LogFileNewCtx(); if (logfile_ctx == NULL) { SCLogDebug("Could not create new LogFileCtx"); return NULL; } if (SCConfLogOpenGeneric(conf, logfile_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { LogFileFreeCtx(logfile_ctx); return NULL; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) return NULL; output_ctx->data = logfile_ctx; output_ctx->DeInit = LogFileLogDeInitCtx; const char *force_filestore = ConfNodeLookupChildValue(conf, "force-filestore"); if (force_filestore != NULL && ConfValIsTrue(force_filestore)) { FileForceFilestoreEnable(); SCLogInfo("forcing filestore of all files"); } const char *force_magic = ConfNodeLookupChildValue(conf, "force-magic"); if (force_magic != NULL && ConfValIsTrue(force_magic)) { FileForceMagicEnable(); SCLogInfo("forcing magic lookup for logged files"); } const char *force_md5 = ConfNodeLookupChildValue(conf, "force-md5"); if (force_md5 != NULL && ConfValIsTrue(force_md5)) { #ifdef HAVE_NSS FileForceMd5Enable(); SCLogInfo("forcing md5 calculation for logged files"); #else SCLogInfo("md5 calculation requires linking against libnss"); #endif } FileForceTrackingEnable(); SCReturnPtr(output_ctx, "OutputCtx"); }
static OutputInitResult JsonDropLogInitCtx(ConfNode *conf) { OutputInitResult result = { NULL, false }; if (OutputDropLoggerEnable() != 0) { SCLogError(SC_ERR_CONF_YAML_ERROR, "only one 'drop' logger " "can be enabled"); return result; } JsonDropOutputCtx *drop_ctx = SCCalloc(1, sizeof(*drop_ctx)); if (drop_ctx == NULL) return result; drop_ctx->file_ctx = LogFileNewCtx(); if (drop_ctx->file_ctx == NULL) { JsonDropOutputCtxFree(drop_ctx); return result; } if (SCConfLogOpenGeneric(conf, drop_ctx->file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { JsonDropOutputCtxFree(drop_ctx); return result; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { JsonDropOutputCtxFree(drop_ctx); return result; } if (conf) { const char *extended = ConfNodeLookupChildValue(conf, "alerts"); if (extended != NULL) { if (ConfValIsTrue(extended)) { drop_ctx->flags = LOG_DROP_ALERTS; } } extended = ConfNodeLookupChildValue(conf, "flows"); if (extended != NULL) { if (strcasecmp(extended, "start") == 0) { g_droplog_flows_start = 1; } else if (strcasecmp(extended, "all") == 0) { g_droplog_flows_start = 0; } else { SCLogWarning(SC_ERR_CONF_YAML_ERROR, "valid options for " "'flow' are 'start' and 'all'"); } } } output_ctx->data = drop_ctx; output_ctx->DeInit = JsonDropLogDeInitCtx; result.ctx = output_ctx; result.ok = true; return result; }
/** * \brief Sets up the rule analyzer according to the config * \retval 1 if rule analyzer successfully enabled * \retval 0 if not enabled */ int SetupRuleAnalyzer(void) { ConfNode *conf = ConfGetNode("engine-analysis"); int enabled = 0; if (conf != NULL) { const char *value = ConfNodeLookupChildValue(conf, "rules"); if (value && ConfValIsTrue(value)) { enabled = 1; } else if (value && strcasecmp(value, "warnings-only") == 0) { enabled = 1; rule_warnings_only = 1; } if (enabled) { char *log_dir; log_dir = ConfigGetLogDirectory(); snprintf(log_path, sizeof(log_path), "%s/%s", log_dir, "rules_analysis.txt"); rule_engine_analysis_FD = fopen(log_path, "w"); if (rule_engine_analysis_FD == NULL) { SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", log_path, strerror(errno)); return 0; } SCLogInfo("Engine-Analysis for rules printed to file - %s", log_path); struct timeval tval; struct tm *tms; gettimeofday(&tval, NULL); struct tm local_tm; tms = SCLocalTime(tval.tv_sec, &local_tm); fprintf(rule_engine_analysis_FD, "----------------------------------------------" "---------------------\n"); fprintf(rule_engine_analysis_FD, "Date: %" PRId32 "/%" PRId32 "/%04d -- " "%02d:%02d:%02d\n", tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min, tms->tm_sec); fprintf(rule_engine_analysis_FD, "----------------------------------------------" "---------------------\n"); /*compile regex's for rule analysis*/ if (PerCentEncodingSetup()== 0) { fprintf(rule_engine_analysis_FD, "Error compiling regex; can't check for percent encoding in normalized http content.\n"); } } } else { SCLogInfo("Conf parameter \"engine-analysis.rules\" not found. " "Defaulting to not printing the rules analysis report."); } if (!enabled) { SCLogInfo("Engine-Analysis for rules disabled in conf file."); return 0; } return 1; }
/** \brief Create a new tls log LogFileCtx. * \param conf Pointer to ConfNode containing this loggers configuration. * \return NULL if failure, LogFileCtx* to the file_ctx if succesful * */ static OutputCtx *LogTlsLogInitCtx(ConfNode *conf) { if (OutputTlsLoggerEnable() != 0) { SCLogError(SC_ERR_CONF_YAML_ERROR, "only one 'tls' logger " "can be enabled"); return NULL; } LogFileCtx* file_ctx = LogFileNewCtx(); if (file_ctx == NULL) { SCLogError(SC_ERR_TLS_LOG_GENERIC, "LogTlsLogInitCtx: Couldn't " "create new file_ctx"); return NULL; } if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { goto filectx_error; } LogTlsFileCtx *tlslog_ctx = SCCalloc(1, sizeof(LogTlsFileCtx)); if (unlikely(tlslog_ctx == NULL)) goto filectx_error; tlslog_ctx->file_ctx = file_ctx; const char *extended = ConfNodeLookupChildValue(conf, "extended"); if (extended == NULL) { tlslog_ctx->flags |= LOG_TLS_DEFAULT; } else { if (ConfValIsTrue(extended)) { tlslog_ctx->flags |= LOG_TLS_EXTENDED; } } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) goto tlslog_error; output_ctx->data = tlslog_ctx; output_ctx->DeInit = LogTlsLogDeInitCtx; SCLogDebug("TLS log output initialized"); /* enable the logger for the app layer */ AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_TLS); return output_ctx; tlslog_error: SCFree(tlslog_ctx); filectx_error: LogFileFreeCtx(file_ctx); return NULL; }
/** \brief Create a new http log LogFileCtx. * \param conf Pointer to ConfNode containing this loggers configuration. * \return NULL if failure, LogFileCtx* to the file_ctx if succesful * */ static OutputCtx *OutputFileLogInitSub(ConfNode *conf, OutputCtx *parent_ctx) { OutputJsonCtx *ojc = parent_ctx->data; OutputFileCtx *output_file_ctx = SCMalloc(sizeof(OutputFileCtx)); if (unlikely(output_file_ctx == NULL)) return NULL; OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { SCFree(output_file_ctx); return NULL; } output_file_ctx->file_ctx = ojc->file_ctx; if (conf) { const char *force_filestore = ConfNodeLookupChildValue(conf, "force-filestore"); if (force_filestore != NULL && ConfValIsTrue(force_filestore)) { FileForceFilestoreEnable(); SCLogConfig("forcing filestore of all files"); } const char *force_magic = ConfNodeLookupChildValue(conf, "force-magic"); if (force_magic != NULL && ConfValIsTrue(force_magic)) { FileForceMagicEnable(); SCLogConfig("forcing magic lookup for logged files"); } FileForceHashParseCfg(conf); } output_ctx->data = output_file_ctx; output_ctx->DeInit = OutputFileLogDeinitSub; FileForceTrackingEnable(); return output_ctx; }
OutputCtx *OutputTlsLogInit(ConfNode *conf) { if (OutputTlsLoggerEnable() != 0) { SCLogError(SC_ERR_CONF_YAML_ERROR, "only one 'tls' logger " "can be enabled"); return NULL; } LogFileCtx *file_ctx = LogFileNewCtx(); if(file_ctx == NULL) { SCLogError(SC_ERR_HTTP_LOG_GENERIC, "couldn't create new file_ctx"); return NULL; } if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME) < 0) { LogFileFreeCtx(file_ctx); return NULL; } OutputTlsCtx *tls_ctx = SCMalloc(sizeof(OutputTlsCtx)); if (unlikely(tls_ctx == NULL)) { LogFileFreeCtx(file_ctx); return NULL; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { LogFileFreeCtx(file_ctx); SCFree(tls_ctx); return NULL; } tls_ctx->file_ctx = file_ctx; tls_ctx->flags = LOG_TLS_DEFAULT; if (conf) { const char *extended = ConfNodeLookupChildValue(conf, "extended"); if (extended != NULL) { if (ConfValIsTrue(extended)) { tls_ctx->flags = LOG_TLS_EXTENDED; } } } output_ctx->data = tls_ctx; output_ctx->DeInit = OutputTlsLogDeinit; return output_ctx; }
/** \brief open the indicated file, logging any errors * \param path filesystem path to open * \param append_setting open file with O_APPEND: "yes" or "no" * \retval FILE* on success * \retval NULL on error */ static FILE * SCLogOpenFileFp(const char *path, const char *append_setting) { FILE *ret = NULL; if (ConfValIsTrue(append_setting)) { ret = fopen(path, "a"); } else { ret = fopen(path, "w"); } if (ret == NULL) SCLogError(SC_ERR_FOPEN, "Error opening file: \"%s\": %s", path, strerror(errno)); return ret; }
OutputCtx *OutputHttpLogInit(ConfNode *conf) { LogFileCtx *file_ctx = LogFileNewCtx(); if(file_ctx == NULL) { SCLogError(SC_ERR_HTTP_LOG_GENERIC, "couldn't create new file_ctx"); return NULL; } if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME) < 0) { LogFileFreeCtx(file_ctx); return NULL; } LogHttpFileCtx *http_ctx = SCMalloc(sizeof(LogHttpFileCtx)); if (unlikely(http_ctx == NULL)) { LogFileFreeCtx(file_ctx); return NULL; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { LogFileFreeCtx(file_ctx); SCFree(http_ctx); return NULL; } http_ctx->file_ctx = file_ctx; http_ctx->flags = LOG_HTTP_DEFAULT; if (conf) { const char *extended = ConfNodeLookupChildValue(conf, "extended"); if (extended != NULL) { if (ConfValIsTrue(extended)) { http_ctx->flags = LOG_HTTP_EXTENDED; } } } output_ctx->data = http_ctx; output_ctx->DeInit = NULL; /* enable the logger for the app layer */ AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_HTTP); return output_ctx; }
OutputCtx *OutputTlsLogInit(ConfNode *conf) { LogFileCtx *file_ctx = LogFileNewCtx(); if(file_ctx == NULL) { SCLogError(SC_ERR_TLS_LOG_GENERIC, "couldn't create new file_ctx"); return NULL; } if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { LogFileFreeCtx(file_ctx); return NULL; } OutputTlsCtx *tls_ctx = SCMalloc(sizeof(OutputTlsCtx)); if (unlikely(tls_ctx == NULL)) { LogFileFreeCtx(file_ctx); return NULL; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { LogFileFreeCtx(file_ctx); SCFree(tls_ctx); return NULL; } tls_ctx->file_ctx = file_ctx; tls_ctx->flags = LOG_TLS_DEFAULT; if (conf) { const char *extended = ConfNodeLookupChildValue(conf, "extended"); if (extended != NULL) { if (ConfValIsTrue(extended)) { tls_ctx->flags = LOG_TLS_EXTENDED; } } } output_ctx->data = tls_ctx; output_ctx->DeInit = OutputTlsLogDeinit; AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_TLS); return output_ctx; }
static OutputCtx *JsonDropLogInitCtx(ConfNode *conf) { if (OutputDropLoggerEnable() != 0) { SCLogError(SC_ERR_CONF_YAML_ERROR, "only one 'drop' logger " "can be enabled"); return NULL; } JsonDropOutputCtx *drop_ctx = SCCalloc(1, sizeof(*drop_ctx)); if (drop_ctx == NULL) return NULL; drop_ctx->file_ctx = LogFileNewCtx(); if (drop_ctx->file_ctx == NULL) { JsonDropOutputCtxFree(drop_ctx); return NULL; } if (SCConfLogOpenGeneric(conf, drop_ctx->file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) { JsonDropOutputCtxFree(drop_ctx); return NULL; } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { JsonDropOutputCtxFree(drop_ctx); return NULL; } if (conf) { const char *extended = ConfNodeLookupChildValue(conf, "alerts"); if (extended != NULL) { if (ConfValIsTrue(extended)) { drop_ctx->flags = LOG_DROP_ALERTS; } } } output_ctx->data = drop_ctx; output_ctx->DeInit = JsonDropLogDeInitCtx; return output_ctx; }
/** \brief open the indicated file, logging any errors * \param path filesystem path to open * \param append_setting open file with O_APPEND: "yes" or "no" * \param mode permissions to set on file * \retval FILE* on success * \retval NULL on error */ static FILE * SCLogOpenFileFp(const char *path, const char *append_setting, uint32_t mode) { FILE *ret = NULL; char *filename = SCLogFilenameFromPattern(path); if (filename == NULL) { return NULL; } int rc = SCLogCreateDirectoryTree(filename); if (rc < 0) { SCFree(filename); return NULL; } if (ConfValIsTrue(append_setting)) { ret = fopen(filename, "a"); } else { ret = fopen(filename, "w"); } if (ret == NULL) { SCLogError(SC_ERR_FOPEN, "Error opening file: \"%s\": %s", filename, strerror(errno)); } else { if (mode != 0) { int r = chmod(filename, mode); if (r < 0) { SCLogWarning(SC_WARN_CHMOD, "Could not chmod %s to %u: %s", filename, mode, strerror(errno)); } } } SCFree(filename); return ret; }
OutputCtx *OutputTlsLogInitSub(ConfNode *conf, OutputCtx *parent_ctx) { AlertJsonThread *ajt = parent_ctx->data; if (OutputTlsLoggerEnable() != 0) { SCLogError(SC_ERR_CONF_YAML_ERROR, "only one 'tls' logger " "can be enabled"); return NULL; } OutputTlsCtx *tls_ctx = SCMalloc(sizeof(OutputTlsCtx)); if (unlikely(tls_ctx == NULL)) return NULL; OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) { SCFree(tls_ctx); return NULL; } tls_ctx->file_ctx = ajt->file_ctx; tls_ctx->flags = LOG_TLS_DEFAULT; if (conf) { const char *extended = ConfNodeLookupChildValue(conf, "extended"); if (extended != NULL) { if (ConfValIsTrue(extended)) { tls_ctx->flags = LOG_TLS_EXTENDED; } } } output_ctx->data = tls_ctx; output_ctx->DeInit = OutputTlsLogDeinitSub; return output_ctx; }
/** \brief Read the config set the file pointer, open the file * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx() * \param filename name of log file * \param mode append mode (bool) * \return -1 if failure, 0 if succesful * */ static int AlertPcapInfoOpenFileCtx(LogFileCtx *file_ctx, const char *filename, const char *mode) { char log_path[PATH_MAX]; char *log_dir; log_dir = ConfigGetLogDirectory(); snprintf(log_path, PATH_MAX, "%s/%s", log_dir, filename); if (ConfValIsTrue(mode)) { file_ctx->fp = fopen(log_path, "a"); } else { file_ctx->fp = fopen(log_path, "w"); } if (file_ctx->fp == NULL) { SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", log_path, strerror(errno)); return -1; } return 0; }
/** \brief initialize the configuration * \warning Not thread safe */ void DefragInitConfig(char quiet) { SCLogDebug("initializing defrag engine..."); memset(&defrag_config, 0, sizeof(defrag_config)); //SC_ATOMIC_INIT(flow_flags); SC_ATOMIC_INIT(defragtracker_counter); SC_ATOMIC_INIT(defrag_memuse); SC_ATOMIC_INIT(defragtracker_prune_idx); DefragTrackerQueueInit(&defragtracker_spare_q); /* set defaults */ defrag_config.hash_rand = (uint32_t)RandomGet(); defrag_config.hash_size = DEFRAG_DEFAULT_HASHSIZE; defrag_config.memcap = DEFRAG_DEFAULT_MEMCAP; defrag_config.prealloc = DEFRAG_DEFAULT_PREALLOC; /* Check if we have memcap and hash_size defined at config */ const char *conf_val; uint32_t configval = 0; /** set config values for memcap, prealloc and hash_size */ if ((ConfGet("defrag.memcap", &conf_val)) == 1) { if (ParseSizeStringU64(conf_val, &defrag_config.memcap) < 0) { SCLogError(SC_ERR_SIZE_PARSE, "Error parsing defrag.memcap " "from conf file - %s. Killing engine", conf_val); exit(EXIT_FAILURE); } } if ((ConfGet("defrag.hash-size", &conf_val)) == 1) { if (ByteExtractStringUint32(&configval, 10, strlen(conf_val), conf_val) > 0) { defrag_config.hash_size = configval; } else { WarnInvalidConfEntry("defrag.hash-size", "%"PRIu32, defrag_config.hash_size); } } if ((ConfGet("defrag.trackers", &conf_val)) == 1) { if (ByteExtractStringUint32(&configval, 10, strlen(conf_val), conf_val) > 0) { defrag_config.prealloc = configval; } else { WarnInvalidConfEntry("defrag.trackers", "%"PRIu32, defrag_config.prealloc); } } SCLogDebug("DefragTracker config from suricata.yaml: memcap: %"PRIu64", hash-size: " "%"PRIu32", prealloc: %"PRIu32, defrag_config.memcap, defrag_config.hash_size, defrag_config.prealloc); /* alloc hash memory */ uint64_t hash_size = defrag_config.hash_size * sizeof(DefragTrackerHashRow); if (!(DEFRAG_CHECK_MEMCAP(hash_size))) { SCLogError(SC_ERR_DEFRAG_INIT, "allocating defrag hash failed: " "max defrag memcap is smaller than projected hash size. " "Memcap: %"PRIu64", Hash table size %"PRIu64". Calculate " "total hash size by multiplying \"defrag.hash-size\" with %"PRIuMAX", " "which is the hash bucket size.", defrag_config.memcap, hash_size, (uintmax_t)sizeof(DefragTrackerHashRow)); exit(EXIT_FAILURE); } defragtracker_hash = SCCalloc(defrag_config.hash_size, sizeof(DefragTrackerHashRow)); if (unlikely(defragtracker_hash == NULL)) { SCLogError(SC_ERR_FATAL, "Fatal error encountered in DefragTrackerInitConfig. Exiting..."); exit(EXIT_FAILURE); } memset(defragtracker_hash, 0, defrag_config.hash_size * sizeof(DefragTrackerHashRow)); uint32_t i = 0; for (i = 0; i < defrag_config.hash_size; i++) { DRLOCK_INIT(&defragtracker_hash[i]); } (void) SC_ATOMIC_ADD(defrag_memuse, (defrag_config.hash_size * sizeof(DefragTrackerHashRow))); if (quiet == FALSE) { SCLogConfig("allocated %"PRIu64" bytes of memory for the defrag hash... " "%" PRIu32 " buckets of size %" PRIuMAX "", SC_ATOMIC_GET(defrag_memuse), defrag_config.hash_size, (uintmax_t)sizeof(DefragTrackerHashRow)); } if ((ConfGet("defrag.prealloc", &conf_val)) == 1) { if (ConfValIsTrue(conf_val)) { /* pre allocate defrag trackers */ for (i = 0; i < defrag_config.prealloc; i++) { if (!(DEFRAG_CHECK_MEMCAP(sizeof(DefragTracker)))) { SCLogError(SC_ERR_DEFRAG_INIT, "preallocating defrag trackers failed: " "max defrag memcap reached. Memcap %"PRIu64", " "Memuse %"PRIu64".", defrag_config.memcap, ((uint64_t)SC_ATOMIC_GET(defrag_memuse) + (uint64_t)sizeof(DefragTracker))); exit(EXIT_FAILURE); } DefragTracker *h = DefragTrackerAlloc(); if (h == NULL) { SCLogError(SC_ERR_DEFRAG_INIT, "preallocating defrag failed: %s", strerror(errno)); exit(EXIT_FAILURE); } DefragTrackerEnqueue(&defragtracker_spare_q,h); } if (quiet == FALSE) { SCLogConfig("preallocated %" PRIu32 " defrag trackers of size %" PRIuMAX "", defragtracker_spare_q.len, (uintmax_t)sizeof(DefragTracker)); } } } if (quiet == FALSE) { SCLogConfig("defrag memory usage: %"PRIu64" bytes, maximum: %"PRIu64, SC_ATOMIC_GET(defrag_memuse), defrag_config.memcap); } return; }
/** * \brief Initialize profiling. */ void SCProfilingInit(void) { ConfNode *conf; SC_ATOMIC_INIT(samples); intmax_t rate_v = 0; (void)ConfGetInt("profiling.sample-rate", &rate_v); if (rate_v > 0 && rate_v < INT_MAX) { rate = (int)rate_v; if (rate != 1) SCLogInfo("profiling runs for every %dth packet", rate); else SCLogInfo("profiling runs for every packet"); } conf = ConfGetNode("profiling.packets"); if (conf != NULL) { if (ConfNodeChildValueIsTrue(conf, "enabled")) { profiling_packets_enabled = 1; if (pthread_mutex_init(&packet_profile_lock, NULL) != 0) { SCLogError(SC_ERR_MUTEX, "Failed to initialize packet profiling mutex."); exit(EXIT_FAILURE); } memset(&packet_profile_data4, 0, sizeof(packet_profile_data4)); memset(&packet_profile_data6, 0, sizeof(packet_profile_data6)); memset(&packet_profile_tmm_data4, 0, sizeof(packet_profile_tmm_data4)); memset(&packet_profile_tmm_data6, 0, sizeof(packet_profile_tmm_data6)); memset(&packet_profile_app_data4, 0, sizeof(packet_profile_app_data4)); memset(&packet_profile_app_data6, 0, sizeof(packet_profile_app_data6)); memset(&packet_profile_app_pd_data4, 0, sizeof(packet_profile_app_pd_data4)); memset(&packet_profile_app_pd_data6, 0, sizeof(packet_profile_app_pd_data6)); memset(&packet_profile_detect_data4, 0, sizeof(packet_profile_detect_data4)); memset(&packet_profile_detect_data6, 0, sizeof(packet_profile_detect_data6)); memset(&packet_profile_log_data4, 0, sizeof(packet_profile_log_data4)); memset(&packet_profile_log_data6, 0, sizeof(packet_profile_log_data6)); memset(&packet_profile_flowworker_data, 0, sizeof(packet_profile_flowworker_data)); const char *filename = ConfNodeLookupChildValue(conf, "filename"); if (filename != NULL) { char *log_dir; log_dir = ConfigGetLogDirectory(); profiling_packets_file_name = SCMalloc(PATH_MAX); if (unlikely(profiling_packets_file_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "can't duplicate file name"); exit(EXIT_FAILURE); } snprintf(profiling_packets_file_name, PATH_MAX, "%s/%s", log_dir, filename); const char *v = ConfNodeLookupChildValue(conf, "append"); if (v == NULL || ConfValIsTrue(v)) { profiling_packets_file_mode = "a"; } else { profiling_packets_file_mode = "w"; } profiling_packets_output_to_file = 1; } } conf = ConfGetNode("profiling.packets.csv"); if (conf != NULL) { if (ConfNodeChildValueIsTrue(conf, "enabled")) { const char *filename = ConfNodeLookupChildValue(conf, "filename"); if (filename == NULL) { filename = "packet_profile.csv"; } char *log_dir; log_dir = ConfigGetLogDirectory(); profiling_csv_file_name = SCMalloc(PATH_MAX); if (unlikely(profiling_csv_file_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "out of memory"); exit(EXIT_FAILURE); } snprintf(profiling_csv_file_name, PATH_MAX, "%s/%s", log_dir, filename); packet_profile_csv_fp = fopen(profiling_csv_file_name, "w"); if (packet_profile_csv_fp == NULL) { return; } fprintf(packet_profile_csv_fp, "pcap_cnt,ipver,ipproto,total,"); int i; for (i = 0; i < TMM_SIZE; i++) { fprintf(packet_profile_csv_fp, "%s,", TmModuleTmmIdToString(i)); } fprintf(packet_profile_csv_fp, "threading,"); for (i = 0; i < ALPROTO_MAX; i++) { fprintf(packet_profile_csv_fp, "%s,", AppProtoToString(i)); } fprintf(packet_profile_csv_fp, "proto detect,"); for (i = 0; i < PROF_DETECT_SIZE; i++) { fprintf(packet_profile_csv_fp, "%s,", PacketProfileDetectIdToString(i)); } fprintf(packet_profile_csv_fp, "\n"); profiling_packets_csv_enabled = 1; } } } conf = ConfGetNode("profiling.locks"); if (conf != NULL) { if (ConfNodeChildValueIsTrue(conf, "enabled")) { #ifndef PROFILE_LOCKING SCLogWarning(SC_WARN_PROFILE, "lock profiling not compiled in. Add --enable-profiling-locks to configure."); #else profiling_locks_enabled = 1; LockRecordInitHash(); const char *filename = ConfNodeLookupChildValue(conf, "filename"); if (filename != NULL) { char *log_dir; log_dir = ConfigGetLogDirectory(); profiling_locks_file_name = SCMalloc(PATH_MAX); if (unlikely(profiling_locks_file_name == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "can't duplicate file name"); exit(EXIT_FAILURE); } snprintf(profiling_locks_file_name, PATH_MAX, "%s/%s", log_dir, filename); const char *v = ConfNodeLookupChildValue(conf, "append"); if (v == NULL || ConfValIsTrue(v)) { profiling_locks_file_mode = "a"; } else { profiling_locks_file_mode = "w"; } profiling_locks_output_to_file = 1; } #endif } } }
/** * \brief extract information from config file * * The returned structure will be freed by the thread init function. * This is thus necessary to or copy the structure before giving it * to thread or to reparse the file for each thread (and thus have * new structure. * * \return a NetmapIfaceConfig corresponding to the interface name */ static void *ParseNetmapConfig(const char *iface_name) { char *threadsstr = NULL; ConfNode *if_root; ConfNode *if_default = NULL; ConfNode *netmap_node; NetmapIfaceConfig *aconf = SCMalloc(sizeof(*aconf)); char *tmpctype; char *copymodestr; int boolval; char *bpf_filter = NULL; char *out_iface = NULL; if (unlikely(aconf == NULL)) { return NULL; } if (iface_name == NULL) { SCFree(aconf); return NULL; } memset(aconf, 0, sizeof(*aconf)); aconf->DerefFunc = NetmapDerefConfig; aconf->threads = 1; aconf->promisc = 1; aconf->checksum_mode = CHECKSUM_VALIDATION_AUTO; aconf->copy_mode = NETMAP_COPY_MODE_NONE; strlcpy(aconf->iface_name, iface_name, sizeof(aconf->iface_name)); SC_ATOMIC_INIT(aconf->ref); (void) SC_ATOMIC_ADD(aconf->ref, 1); strlcpy(aconf->iface, aconf->iface_name, sizeof(aconf->iface)); if (aconf->iface[0]) { size_t len = strlen(aconf->iface); if (aconf->iface[len-1] == '+') { aconf->iface[len-1] = '\0'; aconf->iface_sw = 1; } } if (ConfGet("bpf-filter", &bpf_filter) == 1) { if (strlen(bpf_filter) > 0) { aconf->bpf_filter = bpf_filter; SCLogInfo("Going to use command-line provided bpf filter '%s'", aconf->bpf_filter); } } /* Find initial node */ netmap_node = ConfGetNode("netmap"); if (netmap_node == NULL) { SCLogInfo("Unable to find netmap config using default value"); return aconf; } if_root = ConfFindDeviceConfig(netmap_node, aconf->iface_name); if_default = ConfFindDeviceConfig(netmap_node, "default"); if (if_root == NULL && if_default == NULL) { SCLogInfo("Unable to find netmap config for " "interface \"%s\" or \"default\", using default value", aconf->iface_name); return aconf; } /* If there is no setting for current interface use default one as main iface */ if (if_root == NULL) { if_root = if_default; if_default = NULL; } if (ConfGetChildValueWithDefault(if_root, if_default, "threads", &threadsstr) != 1) { aconf->threads = 1; } else { if (strcmp(threadsstr, "auto") == 0) { aconf->threads = GetIfaceRSSQueuesNum(aconf->iface); } else { aconf->threads = (uint8_t)atoi(threadsstr); } } if (aconf->threads <= 0) { aconf->threads = 1; } if (aconf->threads) { SCLogInfo("Using %d threads for interface %s", aconf->threads, aconf->iface_name); } if (ConfGetChildValueWithDefault(if_root, if_default, "copy-iface", &out_iface) == 1) { if (strlen(out_iface) > 0) { aconf->out_iface_name = out_iface; } } if (ConfGetChildValueWithDefault(if_root, if_default, "copy-mode", ©modestr) == 1) { if (aconf->out_iface_name == NULL) { SCLogInfo("Copy mode activated but no destination" " iface. Disabling feature"); } else if (strlen(copymodestr) <= 0) { aconf->out_iface_name = NULL; } else if (strcmp(copymodestr, "ips") == 0) { SCLogInfo("Netmap IPS mode activated %s->%s", aconf->iface_name, aconf->out_iface_name); aconf->copy_mode = NETMAP_COPY_MODE_IPS; } else if (strcmp(copymodestr, "tap") == 0) { SCLogInfo("Netmap TAP mode activated %s->%s", aconf->iface_name, aconf->out_iface_name); aconf->copy_mode = NETMAP_COPY_MODE_TAP; } else { SCLogInfo("Invalid mode (not in tap, ips)"); } } if (aconf->out_iface_name && aconf->out_iface_name[0]) { strlcpy(aconf->out_iface, aconf->out_iface_name, sizeof(aconf->out_iface)); size_t len = strlen(aconf->out_iface); if (aconf->out_iface[len-1] == '+') { aconf->out_iface[len-1] = '\0'; aconf->out_iface_sw = 1; } } SC_ATOMIC_RESET(aconf->ref); (void) SC_ATOMIC_ADD(aconf->ref, aconf->threads); /* load netmap bpf filter */ /* command line value has precedence */ if (ConfGet("bpf-filter", &bpf_filter) != 1) { if (ConfGetChildValueWithDefault(if_root, if_default, "bpf-filter", &bpf_filter) == 1) { if (strlen(bpf_filter) > 0) { aconf->bpf_filter = bpf_filter; SCLogInfo("Going to use bpf filter %s", aconf->bpf_filter); } } } (void)ConfGetChildValueBoolWithDefault(if_root, if_default, "disable-promisc", (int *)&boolval); if (boolval) { SCLogInfo("Disabling promiscuous mode on iface %s", aconf->iface); aconf->promisc = 0; } if (ConfGetChildValueWithDefault(if_root, if_default, "checksum-checks", &tmpctype) == 1) { if (strcmp(tmpctype, "auto") == 0) { aconf->checksum_mode = CHECKSUM_VALIDATION_AUTO; } else if (ConfValIsTrue(tmpctype)) { aconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE; } else if (ConfValIsFalse(tmpctype)) { aconf->checksum_mode = CHECKSUM_VALIDATION_DISABLE; } else { SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid value for checksum-checks for %s", aconf->iface_name); } } return aconf; }
/** * \brief Create a new LogFileCtx for "fast" output style. * \param conf The configuration node for this output. * \return A LogFileCtx pointer on success, NULL on failure. */ static OutputCtx *JsonAlertLogInitCtxSub(ConfNode *conf, OutputCtx *parent_ctx) { AlertJsonThread *ajt = parent_ctx->data; AlertJsonOutputCtx *json_output_ctx = NULL; HttpXFFCfg *xff_cfg = NULL; OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (unlikely(output_ctx == NULL)) return NULL; json_output_ctx = SCMalloc(sizeof(AlertJsonOutputCtx)); if (unlikely(json_output_ctx == NULL)) { goto error; } memset(json_output_ctx, 0, sizeof(AlertJsonOutputCtx)); xff_cfg = SCMalloc(sizeof(HttpXFFCfg)); if (unlikely(xff_cfg == NULL)) { goto error; } memset(xff_cfg, 0, sizeof(HttpXFFCfg)); json_output_ctx->file_ctx = ajt->file_ctx; json_output_ctx->xff_cfg = xff_cfg; if (conf != NULL) { const char *payload = ConfNodeLookupChildValue(conf, "payload"); const char *packet = ConfNodeLookupChildValue(conf, "packet"); const char *payload_printable = ConfNodeLookupChildValue(conf, "payload-printable"); const char *http = ConfNodeLookupChildValue(conf, "http"); const char *tls = ConfNodeLookupChildValue(conf, "tls"); const char *ssh = ConfNodeLookupChildValue(conf, "ssh"); if (ssh != NULL) { if (ConfValIsTrue(ssh)) { json_output_ctx->flags |= LOG_JSON_SSH; } } if (tls != NULL) { if (ConfValIsTrue(tls)) { json_output_ctx->flags |= LOG_JSON_TLS; } } if (http != NULL) { if (ConfValIsTrue(http)) { json_output_ctx->flags |= LOG_JSON_HTTP; } } if (payload_printable != NULL) { if (ConfValIsTrue(payload_printable)) { json_output_ctx->flags |= LOG_JSON_PAYLOAD; } } if (payload != NULL) { if (ConfValIsTrue(payload)) { json_output_ctx->flags |= LOG_JSON_PAYLOAD_BASE64; } } if (packet != NULL) { if (ConfValIsTrue(packet)) { json_output_ctx->flags |= LOG_JSON_PACKET; } } HttpXFFGetCfg(conf, xff_cfg); } output_ctx->data = json_output_ctx; output_ctx->DeInit = JsonAlertLogDeInitCtxSub; return output_ctx; error: if (json_output_ctx != NULL) { SCFree(json_output_ctx); } if (output_ctx != NULL) { SCFree(output_ctx); } return NULL; }
static void XffSetup(AlertJsonOutputCtx *json_output_ctx, ConfNode *conf) { HttpXFFCfg *xff_cfg = NULL; xff_cfg = SCMalloc(sizeof(HttpXFFCfg)); if (unlikely(xff_cfg == NULL)) { return; } memset(xff_cfg, 0, sizeof(HttpXFFCfg)); json_output_ctx->xff_cfg = xff_cfg; uint32_t payload_buffer_size = JSON_STREAM_BUFFER_SIZE; if (conf != NULL) { const char *payload = ConfNodeLookupChildValue(conf, "payload"); const char *payload_buffer_value = ConfNodeLookupChildValue(conf, "payload-buffer-size"); const char *packet = ConfNodeLookupChildValue(conf, "packet"); const char *payload_printable = ConfNodeLookupChildValue(conf, "payload-printable"); const char *http = ConfNodeLookupChildValue(conf, "http"); const char *tls = ConfNodeLookupChildValue(conf, "tls"); const char *ssh = ConfNodeLookupChildValue(conf, "ssh"); const char *smtp = ConfNodeLookupChildValue(conf, "smtp"); const char *tagged_packets = ConfNodeLookupChildValue(conf, "tagged-packets"); if (ssh != NULL) { if (ConfValIsTrue(ssh)) { json_output_ctx->flags |= LOG_JSON_SSH; } } if (tls != NULL) { if (ConfValIsTrue(tls)) { json_output_ctx->flags |= LOG_JSON_TLS; } } if (http != NULL) { if (ConfValIsTrue(http)) { json_output_ctx->flags |= LOG_JSON_HTTP; } } if (smtp != NULL) { if (ConfValIsTrue(smtp)) { json_output_ctx->flags |= LOG_JSON_SMTP; } } if (payload_printable != NULL) { if (ConfValIsTrue(payload_printable)) { json_output_ctx->flags |= LOG_JSON_PAYLOAD; } } if (payload != NULL) { if (ConfValIsTrue(payload)) { json_output_ctx->flags |= LOG_JSON_PAYLOAD_BASE64; } } if (payload_buffer_value != NULL) { uint32_t value; if (ParseSizeStringU32(payload_buffer_value, &value) < 0) { SCLogError(SC_ERR_ALERT_PAYLOAD_BUFFER, "Error parsing " "payload-buffer-size - %s. Killing engine", payload_buffer_value); exit(EXIT_FAILURE); } else { payload_buffer_size = value; } } if (packet != NULL) { if (ConfValIsTrue(packet)) { json_output_ctx->flags |= LOG_JSON_PACKET; } } if (tagged_packets != NULL) { if (ConfValIsTrue(tagged_packets)) { json_output_ctx->flags |= LOG_JSON_TAGGED_PACKETS; } } json_output_ctx->payload_buffer_size = payload_buffer_size; HttpXFFGetCfg(conf, xff_cfg); } }
/** \brief Create a new http log LogFileCtx. * \param conf Pointer to ConfNode containing this loggers configuration. * \return NULL if failure, LogFileCtx* to the file_ctx if succesful * */ OutputCtx *LogHttpLogInitCtx(ConfNode *conf) { LogFileCtx* file_ctx = LogFileNewCtx(); const char *p, *np; uint32_t n; if(file_ctx == NULL) { SCLogError(SC_ERR_HTTP_LOG_GENERIC, "couldn't create new file_ctx"); return NULL; } if (SCConfLogOpenGeneric(conf, file_ctx, DEFAULT_LOG_FILENAME) < 0) { LogFileFreeCtx(file_ctx); return NULL; } LogHttpFileCtx *httplog_ctx = SCMalloc(sizeof(LogHttpFileCtx)); if (httplog_ctx == NULL) { LogFileFreeCtx(file_ctx); return NULL; } memset(httplog_ctx, 0x00, sizeof(LogHttpFileCtx)); httplog_ctx->file_ctx = file_ctx; httplog_ctx->cf_n=0; const char *extended = ConfNodeLookupChildValue(conf, "extended"); const char *custom = ConfNodeLookupChildValue(conf, "custom"); const char *customformat = ConfNodeLookupChildValue(conf, "customformat"); /* If custom logging format is selected, lets parse it */ if (custom != NULL && customformat != NULL && ConfValIsTrue(custom)) { p=customformat; httplog_ctx->flags |= LOG_HTTP_CUSTOM; for (httplog_ctx->cf_n = 0; httplog_ctx->cf_n < LOG_HTTP_MAXN_NODES-1 && p && *p != '\0'; httplog_ctx->cf_n++){ httplog_ctx->cf_nodes[httplog_ctx->cf_n] = SCMalloc(sizeof(LogHttpCustomFormatNode)); if (httplog_ctx->cf_nodes[httplog_ctx->cf_n] == NULL) { for (n = 0; n < httplog_ctx->cf_n; n++) { SCFree(httplog_ctx->cf_nodes[n]); } LogFileFreeCtx(file_ctx); SCFree(httplog_ctx); return NULL; } if (*p != '%'){ /* Literal found in format string */ httplog_ctx->cf_nodes[httplog_ctx->cf_n]->type = LOG_HTTP_CF_LITERAL; np = strchr(p, '%'); if (np == NULL){ n = LOG_HTTP_NODE_STRLEN-2; np = NULL; /* End */ }else{ n = np-p; } strlcpy(httplog_ctx->cf_nodes[httplog_ctx->cf_n]->data,p,n+1); p = np; } else { /* Non Literal found in format string */ p++; if (*p == '{') { /* Simple format char */ np = strchr(p, '}'); if (np != NULL && np-p > 1 && np-p < LOG_HTTP_NODE_STRLEN-2) { p++; n = np-p; strlcpy(httplog_ctx->cf_nodes[httplog_ctx->cf_n]->data, p, n+1); p = np; } p++; } else { httplog_ctx->cf_nodes[httplog_ctx->cf_n]->data[0] = '\0'; } httplog_ctx->cf_nodes[httplog_ctx->cf_n]->type = *p; if (*p == '%'){ httplog_ctx->cf_nodes[httplog_ctx->cf_n]->type = LOG_HTTP_CF_LITERAL; strlcpy(httplog_ctx->cf_nodes[httplog_ctx->cf_n]->data, "%", 2); } p++; } } } else { if (extended == NULL) { httplog_ctx->flags |= LOG_HTTP_DEFAULT; } else { if (ConfValIsTrue(extended)) { httplog_ctx->flags |= LOG_HTTP_EXTENDED; } } } OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx)); if (output_ctx == NULL) { for (n = 0; n < httplog_ctx->cf_n; n++) { SCFree(httplog_ctx->cf_nodes[n]); } LogFileFreeCtx(file_ctx); SCFree(httplog_ctx); return NULL; } output_ctx->data = httplog_ctx; output_ctx->DeInit = LogHttpLogDeInitCtx; SCLogDebug("HTTP log output initialized"); return output_ctx; }