📄 op_acid_db.c
字号:
/* $Id: op_acid_db.c,v 1.16 2004/04/03 19:57:32 andrewbaker Exp $ *//*** Copyright (C) 2001-2002 Andrew R. Baker <andrewb@snort.org>**** This program is distributed under the terms of version 1.0 of the ** Q Public License. See LICENSE.QPL for further details.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.***//* I N C L U D E S *****************************************************/#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <netinet/in.h>#include <time.h>#include <errno.h>#include <unistd.h>#include "ConfigFile.h"#include "mstring.h"#include "sid.h"#include "classification.h"#include "util.h"#include "input-plugins/dp_alert.h"#include "input-plugins/dp_log.h"#include "op_plugbase.h"#include "op_decode.h"#include "event.h"#include <ctype.h>#ifdef ENABLE_MYSQL#include <mysql.h>#include <errmsg.h>#endif /* ENABLE_MYSQL */#ifdef ENABLE_POSTGRES#include <libpq-fe.h>#endif /* ENABLE_POSTGRES *//* D A T A S T R U C T U R E S **************************************/typedef struct _OpAcidDb_Data { u_int8_t flavor; /* what flavor of db? MySQL, postgres, ... */ u_int8_t detail; u_int16_t unused; char *server; char *database; char *user; char *password; int sensor_id; u_int32_t event_id; int linktype; /* db handles go here */#ifdef ENABLE_MYSQL MYSQL *mysql;#endif /* ENABLE_MYSQL */#ifdef ENABLE_POSTGRES PGconn *pq;#endif /* ENABLE_POSTGRES */} OpAcidDb_Data;#define MAX_QUERY_SIZE 8192/* database flavor defines */#define FLAVOR_MYSQL 1#define FLAVOR_POSTGRES 2char *db_flavours[] = {NULL, "mysql", "postgres"};/* Output plugin API functions */int OpAcidDb_Setup(OutputPlugin *, char *args);int OpAcidDb_Exit(OutputPlugin *);int OpAcidDb_Start(OutputPlugin *, void *);int OpAcidDb_Stop(OutputPlugin *);int OpAcidDb_Log(void *, void *);int OpAcidDb_Alert(void *, void *);int OpAcidDb_LogConfig(OutputPlugin *outputPlugin);/* Internal functions */OpAcidDb_Data *OpAcidDb_ParseArgs(char *);int DbClose(OpAcidDb_Data *data);int DbConnect(OpAcidDb_Data *data);u_int32_t AcidDbGetNextCid(OpAcidDb_Data *data);u_int32_t AcidDbGetSensorId(OpAcidDb_Data *data);int AcidDbCheckSchemaVersion(OpAcidDb_Data *data);u_int32_t AcidDbGetSigId(OpAcidDb_Data *, Sid *, ClassType *, unsigned int priority);unsigned int GetAcidDbClassId(OpAcidDb_Data *data, ClassType *class_type);int InsertSigReferences(OpAcidDb_Data *, ReferenceData *, unsigned int sig_id);int InsertIPData(OpAcidDb_Data *data, Packet *p);int InsertICMPData(OpAcidDb_Data *data, Packet *p);int InsertUDPData(OpAcidDb_Data *data, Packet *p);int InsertTCPData(OpAcidDb_Data *data, Packet *p);int InsertPayloadData(OpAcidDb_Data *data, Packet *p);int SelectAsUInt(OpAcidDb_Data *data, char *sql, unsigned int *result);int Insert(OpAcidDb_Data *data, char *sql, unsigned int *row_id);char *EscapeString(OpAcidDb_Data *data, char *string);#ifdef ENABLE_MYSQLint MysqlConnect(OpAcidDb_Data *);int MysqlClose(MYSQL *mysql);int MysqlSelectAsUInt(MYSQL *mysql, char *sql, unsigned int *result);int MysqlInsert(MYSQL *mysql, char *sql, unsigned int *row_id);char *MysqlEscapeString(MYSQL *mysql, char *string);#endif#ifdef ENABLE_POSTGRESint PostgresConnect(OpAcidDb_Data *);int PostgresClose(PGconn *);int PostgresSelectAsUInt(PGconn *, char *sql, unsigned int *result);int PostgresInsert(PGconn *, char *sql);char *PostgresEscapeString(PGconn *, char *string);#endif /* ENABLE_POSTGRES *//* Global variables */static char sql_buffer[MAX_QUERY_SIZE];/* init routine makes this processor available for dataprocessor directives */void OpAcidDb_Init(){ OutputPlugin *outputPlugin; outputPlugin = RegisterOutputPlugin("alert_acid_db", "alert"); outputPlugin->setupFunc = OpAcidDb_Setup; outputPlugin->exitFunc = OpAcidDb_Exit; outputPlugin->startFunc = OpAcidDb_Start; outputPlugin->stopFunc = OpAcidDb_Stop; outputPlugin->outputFunc = OpAcidDb_Alert; outputPlugin->logConfigFunc = OpAcidDb_LogConfig; outputPlugin = RegisterOutputPlugin("log_acid_db", "log"); outputPlugin->setupFunc = OpAcidDb_Setup; outputPlugin->exitFunc = OpAcidDb_Exit; outputPlugin->startFunc = OpAcidDb_Start; outputPlugin->stopFunc = OpAcidDb_Stop; outputPlugin->outputFunc = OpAcidDb_Log; outputPlugin->logConfigFunc = OpAcidDb_LogConfig; }/* Setup the output plugin, process any arguments, link the functions to * the output functional node */int OpAcidDb_Setup(OutputPlugin *outputPlugin, char *args){ /* setup the run time context for this output plugin */ outputPlugin->data = OpAcidDb_ParseArgs(args); return 0;}/* Inverse of the setup function, free memory allocated in Setup * can't free the outputPlugin since it is also the list node itself */int OpAcidDb_Exit(OutputPlugin *outputPlugin){ return 0;}int OpAcidDb_LogConfig(OutputPlugin *outputPlugin){ OpAcidDb_Data *data = NULL; if(!outputPlugin || !outputPlugin->data) return -1; data = (OpAcidDb_Data *)outputPlugin->data; LogMessage("OpAcidDB configured\n"); LogMessage(" Database Flavour: %s\n", db_flavours[data->flavor]); LogMessage(" Detail Level: %s\n", data->detail == 1 ? "Full" : "Fast"); LogMessage(" Database Server: %s\n", data->server); LogMessage(" Database User: %s\n", data->user); return 0;}/* * this function gets called at start time, you should open any output files * or establish DB connections, etc, here */int OpAcidDb_Start(OutputPlugin *outputPlugin, void *spool_header){ OpAcidDb_Data *data = (OpAcidDb_Data *)outputPlugin->data; if(data == NULL) FatalError("ERROR: Unable to find context for AcidDb startup!\n"); if(pv.verbose) { OpAcidDb_LogConfig(outputPlugin); } /* Connect to the database */ if(DbConnect(data)) FatalError("OpAcidDb_: Failed to connect to database: %s:%s@%s/%s\n", data->user, data->password, data->server, data->database); /* check the db schema */ if(AcidDbCheckSchemaVersion(data)) FatalError("OpAcidDb_: database schema mismatch\n"); /* if sensor id == 0, then we attempt attempt to determine it dynamically */ if(data->sensor_id == 0) { data->sensor_id = AcidDbGetSensorId(data); /* XXX: Error checking */ } /* Get the next cid from the database */ data->event_id = AcidDbGetNextCid(data); if(pv.verbose) { LogMessage("SensorID: %i\n", data->sensor_id); LogMessage("Next CID: %i\n", data->event_id); } return 0;}int OpAcidDb_Stop(OutputPlugin *outputPlugin){ OpAcidDb_Data *data = (OpAcidDb_Data *)outputPlugin->data; if(data == NULL) FatalError("ERROR: Unable to find context for AcidDb startup!\n"); /* close database connection */ DbClose(data); return 0;}int OpAcidDb_Alert(void *context, void *data){ char timestamp[TIMEBUF_SIZE]; Sid *sid = NULL; ClassType *class_type = NULL; UnifiedAlertRecord *record = (UnifiedAlertRecord *)data; OpAcidDb_Data *op_data = (OpAcidDb_Data *)context; u_int32_t acid_sig_id; RenderTimestamp(record->ts.tv_sec, timestamp, TIMEBUF_SIZE); sid = GetSid(record->event.sig_generator, record->event.sig_id); if(sid == NULL) sid = FakeSid(record->event.sig_generator, record->event.sig_id); if(!(class_type = GetClassType(record->event.classification)) && record->event.classification != 0) { LogMessage("WARNING: No ClassType found for classification '%i'\n", record->event.classification); } if((acid_sig_id = AcidDbGetSigId(op_data, sid, class_type, record->event.priority)) == 0) { FatalError("op_acid_db: Failed to retrieve ACID DB sig id\n"); } /* Insert data into the event table */ if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO event(sid, cid, signature, timestamp) " "VALUES('%u', '%u', '%u', '%s')", op_data->sensor_id, op_data->event_id, acid_sig_id, timestamp) < MAX_QUERY_SIZE) { //LogMessage("SQL: %s\n", sql_buffer); Insert(op_data, sql_buffer, NULL); /* XXX: Error checking */ } /* insert data into the ip header table */ if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO iphdr(sid, cid, ip_src, ip_dst, ip_proto) " "VALUES('%u', '%u', '%u', '%u', '%u')", op_data->sensor_id, op_data->event_id, record->sip, record->dip, record->protocol) < MAX_QUERY_SIZE) { Insert(op_data, sql_buffer, NULL); /* XXX: Error checking */ } /* build the protocol specific header information */ switch(record->protocol) { case IPPROTO_TCP: if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO tcphdr (sid, cid, tcp_sport, tcp_dport, " "tcp_flags) VALUES('%u', '%u', '%u', '%u', 0)", op_data->sensor_id, op_data->event_id, record->sp, record->dp) < MAX_QUERY_SIZE) { Insert(op_data, sql_buffer, NULL); /* XXX: Error checking */ } break; case IPPROTO_UDP: if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO udphdr (sid, cid, udp_sport, udp_dport) " "VALUES('%u', '%u', '%u', '%u')", op_data->sensor_id, op_data->event_id, record->sp, record->dp) < MAX_QUERY_SIZE) { Insert(op_data, sql_buffer, NULL); /* XXX: Error checking */ } break; case IPPROTO_ICMP: if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO icmphdr (sid, cid, icmp_type, icmp_code) " "VALUES('%u', '%u', '%u', '%u')", op_data->sensor_id, op_data->event_id, record->sp, record->dp) < MAX_QUERY_SIZE) { Insert(op_data, sql_buffer, NULL); /* XXX: Error Checking */ } break; } ++op_data->event_id; return 0;}int OpAcidDb_Log(void *context, void *data){ char timestamp[TIMEBUF_SIZE]; Sid *sid = NULL; ClassType *class_type; UnifiedLogRecord *record = (UnifiedLogRecord *)data; OpAcidDb_Data *op_data = (OpAcidDb_Data *)context; u_int32_t acid_sig_id; Packet p;#if 0 /* this is broken */ /* skip tagged packets, since the db does not have a mechanism to * deal with them properly */ if(record->log.event.event_reference) { LogMessage("Skipping tagged packet %i\n", record->log.event.event_reference); return 0; }#endif RenderTimestamp(record->log.pkth.ts.tv_sec, timestamp, TIMEBUF_SIZE); sid = GetSid(record->log.event.sig_generator, record->log.event.sig_id); if(sid == NULL) sid = FakeSid(record->log.event.sig_generator, record->log.event.sig_id); class_type = GetClassType(record->log.event.classification); if((acid_sig_id = AcidDbGetSigId(op_data, sid, class_type, record->log.event.priority)) == 0) { FatalError("op_acid_db: Failed to retrieve ACID DB sig id\n"); } /* Insert data into the event table */ if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO event(sid, cid, signature, timestamp) " "VALUES('%u', '%u', '%u', '%s')", op_data->sensor_id, op_data->event_id, acid_sig_id, timestamp) < MAX_QUERY_SIZE) { //LogMessage("SQL: %s\n", sql_buffer); Insert(op_data, sql_buffer, NULL); /* XXX: Error checking */ } /* decode the packet */ if(DecodePacket(&p, &record->log.pkth, record->pkt + 2) == 0) { if(p.iph) { /* Insert ip header information */ InsertIPData(op_data, &p); /* store layer 4 data for non fragmented packets */ if(!(p.pkt_flags & PKT_FRAG_FLAG)) { switch(p.iph->ip_proto) { case IPPROTO_ICMP: InsertICMPData(op_data, &p); break; case IPPROTO_TCP: InsertTCPData(op_data, &p); break; case IPPROTO_UDP: InsertUDPData(op_data, &p); break; } } /* Insert payload data */ if(op_data->detail) InsertPayloadData(op_data, &p); } } ++op_data->event_id; return 0;}int InsertIPData(OpAcidDb_Data *op_data, Packet *p){ if(op_data->detail) { if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO iphdr(sid, cid, ip_src, ip_dst, ip_proto, " "ip_ver, ip_hlen, ip_tos, ip_len, ip_id, ip_flags, ip_off, " "ip_ttl, ip_csum) VALUES('%u', '%u', '%u', '%u', '%u', " "'%u', '%u', '%u', '%u', '%u', '%u', '%u', " "'%u', '%u')", op_data->sensor_id, op_data->event_id, ntohl(p->iph->ip_src.s_addr), ntohl(p->iph->ip_dst.s_addr), p->iph->ip_proto, IP_VER(p->iph), IP_HLEN(p->iph), p->iph->ip_tos, ntohs(p->iph->ip_len), ntohs(p->iph->ip_id),#if defined(WORDS_BIGENDIAN) ((p->iph->ip_off & 0xE000) >> 13), htons(p->iph->ip_off & 0x1FFF),#else ((p->iph->ip_off & 0x00E0) >> 5), htons(p->iph->ip_off & 0xFF1F), #endif p->iph->ip_ttl, htons(p->iph->ip_csum)) < MAX_QUERY_SIZE) { Insert(op_data, sql_buffer, NULL); /* XXX: Error Checking */ } /* XXX: IP Options not handled */ } else { if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO iphdr(sid, cid, ip_src, ip_dst, ip_proto) " "VALUES('%u', '%u', '%u', '%u', '%u')", op_data->sensor_id, op_data->event_id, ntohl(p->iph->ip_src.s_addr), ntohl(p->iph->ip_dst.s_addr), p->iph->ip_proto) < MAX_QUERY_SIZE) { Insert(op_data, sql_buffer, NULL); /* XXX: Error Checking */ } } return 0;}int InsertUDPData(OpAcidDb_Data *op_data, Packet *p){ if(!p->udph) return 0; if(op_data->detail) { if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO udphdr(sid, cid, udp_sport, udp_dport, udp_len, " "udp_csum) VALUES('%u', '%u', '%u', '%u', '%u', '%u')", op_data->sensor_id, op_data->event_id, p->sp, p->dp, ntohs(p->udph->uh_len), ntohs(p->udph->uh_chk)) < MAX_QUERY_SIZE) { Insert(op_data, sql_buffer, NULL); /* XXX: Error Checking */ } } else { /* insert data into the udp header table */ if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO udphdr (sid, cid, udp_sport, udp_dport) " "VALUES('%u', '%u', '%u', '%u')", op_data->sensor_id, op_data->event_id, p->sp,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -