00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026
00027 #ifdef LINUX
00028
00029 #include "spo_plugbase.h"
00030
00031 #include "event.h"
00032 #include "rules.h"
00033 #include "debug.h"
00034 #include "util.h"
00035 #include <sys/socket.h>
00036 #include <sys/un.h>
00037 #include <errno.h>
00038 #include <stdlib.h>
00039
00040
00041 #define SNORT_SUCCESS 0
00042 #define SNORT_EINVAL 1
00043 #define SNORT_ENOENT 2
00044 #define SNORT_ENOMEM 3
00045
00046 static int configured = 0;
00047 static int connected = 0;
00048 static int sock = -1;
00049 static struct sockaddr_un sockAddr;
00050
00051 extern RuleListNode *RuleLists;
00052
00053 typedef struct _SnortActionRequest
00054 {
00055 u_int32_t event_id;
00056 u_int32_t tv_sec;
00057 u_int32_t generator;
00058 u_int32_t sid;
00059 u_int32_t src_ip;
00060 u_int32_t dest_ip;
00061 u_int16_t sport;
00062 u_int16_t dport;
00063 u_int8_t protocol;
00064 } SnortActionRequest;
00065
00066 static void AlertSFSocket_Init(u_char *args);
00067 static void AlertSFSocketSid_Init(u_char *args);
00068 void AlertSFSocket(Packet *packet, char *msg, void *arg, Event *event);
00069
00070 static int AlertSFSocket_Connect(void);
00071 static OptTreeNode *OptTreeNode_Search(u_int32_t sid);
00072 static int SignatureAddOutputFunc(u_int32_t sid,
00073 void (*outputFunc)(Packet *, char *, void *, Event *),
00074 void *args);
00075 int String2ULong(char *string, unsigned long *result);
00076
00077 void AlertSFSocket_Setup(void)
00078 {
00079 RegisterOutputPlugin("alert_sf_socket", NT_OUTPUT_ALERT,
00080 AlertSFSocket_Init);
00081 RegisterOutputPlugin("alert_sf_socket_sid", NT_OUTPUT_ALERT,
00082 AlertSFSocketSid_Init);
00083 DEBUG_WRAP(DebugMessage(DEBUG_INIT,"Output plugin: AlertSFSocket "
00084 "registered\n"););
00085 }
00086
00087
00088 #ifndef UNIX_PATH_MAX
00089 #define UNIX_PATH_MAX 108
00090 #endif
00091
00092 static void AlertSFSocket_Init(u_char *args)
00093 {
00094
00095 char *sockname;
00096
00097 if(!args)
00098 FatalError("ERROR: AlertSFSocket: must specify a socket name\n");
00099
00100 sockname = args;
00101
00102 if(strlen(sockname) == 0)
00103 FatalError("ERROR: AlertSFSocket: must specify a socket name\n");
00104
00105 if(strlen(sockname) > UNIX_PATH_MAX - 1)
00106 FatalError("ERROR: AlertSFSocket: socket name must be less than %i "
00107 "characters\n", UNIX_PATH_MAX - 1);
00108
00109
00110 if((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
00111 {
00112 FatalError("ERROR: Unable to create socket: %s\n", strerror(errno));
00113 }
00114
00115 memset(&sockAddr, 0, sizeof(sockAddr));
00116 sockAddr.sun_family = AF_UNIX;
00117 memcpy(sockAddr.sun_path + 1, sockname, strlen(sockname));
00118
00119 if(AlertSFSocket_Connect() == 0)
00120 connected = 1;
00121
00122 configured = 1;
00123
00124 return;
00125 }
00126
00127 static void AlertSFSocketSid_Init(u_char *args)
00128 {
00129 unsigned long sidValue;
00130 int rval = 0;
00131
00132
00133 if(!configured)
00134 FatalError("AlertSFSocket must be configured before attaching it to a "
00135 "sid");
00136
00137 if(String2ULong(args, &sidValue))
00138 FatalError("Invalid argument '%s' to alert_sf_socket_sid\n", args);
00139
00140 rval = SignatureAddOutputFunc((u_int32_t)sidValue, AlertSFSocket, NULL);
00141
00142 switch(rval)
00143 {
00144 case SNORT_SUCCESS:
00145 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "SFSocket output enabled for "
00146 "sid %u.\n", sidValue););
00147 break;
00148 case SNORT_EINVAL:
00149 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Invalid argument "
00150 "attempting to attach output for sid %u.\n",
00151 sidValue););
00152 break;
00153 case SNORT_ENOENT:
00154 LogMessage("No entry found. SFSocket output not enabled for "
00155 "sid %lu.\n", sidValue);
00156 break;
00157 case SNORT_ENOMEM:
00158 FatalError("Out of memory");
00159 break;
00160 }
00161 }
00162
00163 static int AlertSFSocket_Connect(void)
00164 {
00165
00166 if(sock == -1)
00167 FatalError("ERROR: AlertSFSocket: Invalid socket\n");
00168
00169 if(connect(sock, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) == -1)
00170 {
00171 if(errno == ECONNREFUSED || errno == ENOENT)
00172 {
00173 LogMessage("WARNING: AlertSFSocket: Unable to connect to socket: "
00174 "%s\n", strerror(errno));
00175 return 1;
00176 }
00177 else
00178 {
00179 FatalError("ERROR: AlertSFSocket: Unable to connect to socket "
00180 "(%i): %s\n", errno, strerror(errno));
00181 }
00182 }
00183 return 0;
00184 }
00185
00186
00187 static SnortActionRequest sar;
00188
00189 void AlertSFSocket(Packet *packet, char *msg, void *arg, Event *event)
00190 {
00191 int tries = 0;
00192
00193 if(!event || !packet || !packet->iph)
00194 return;
00195
00196
00197 sar.event_id = event->event_id;
00198 sar.tv_sec = packet->pkth->ts.tv_sec;
00199 sar.generator = event->sig_generator;
00200 sar.sid = event->sig_id;
00201 sar.src_ip = ntohl(packet->iph->ip_src.s_addr);
00202 sar.dest_ip = ntohl(packet->iph->ip_dst.s_addr);
00203 sar.protocol = packet->iph->ip_proto;
00204 if(sar.protocol == IPPROTO_UDP || sar.protocol == IPPROTO_TCP)
00205 {
00206 sar.sport = packet->sp;
00207 sar.dport = packet->dp;
00208 }
00209 else
00210 {
00211 sar.sport = 0;
00212 sar.dport = 0;
00213 }
00214
00215 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"AlertSFSocket fired for sid %u\n",
00216 event->sig_id););
00217
00218 do
00219 {
00220 tries++;
00221
00222 if(!connected)
00223 {
00224 if(AlertSFSocket_Connect() != 0)
00225 break;
00226 connected = 1;
00227 }
00228
00229
00230 if(send(sock, &sar, sizeof(sar), 0) == sizeof(sar))
00231 {
00232
00233 return;
00234 }
00235
00236 if(errno == ENOBUFS)
00237 {
00238 LogMessage("ERROR: AlertSFSocket: out of buffer space\n");
00239 break;
00240 }
00241 else if(errno == ECONNRESET)
00242 {
00243 connected = 0;
00244 LogMessage("WARNING: AlertSFSocket: connection reset, will attempt "
00245 "to reconnect\n");
00246 }
00247 else if(errno == ECONNREFUSED)
00248 {
00249 LogMessage("WARNING: AlertSFSocket: connection refused, "
00250 "will attempt to reconnect\n");
00251 connected = 0;
00252 }
00253 else if(errno == ENOTCONN)
00254 {
00255 LogMessage("WARNING: AlertSFSocket: not connected, "
00256 "will attempt to reconnect\n");
00257 connected = 0;
00258 }
00259 else
00260 {
00261 LogMessage("ERROR: AlertSFSocket: unhandled error '%i' in send(): "
00262 "%s\n", errno, strerror(errno));
00263 connected = 0;
00264 }
00265 } while(tries <= 1);
00266 LogMessage("ERROR: AlertSFSocket: Alert not sent\n");
00267 return;
00268 }
00269
00270 static int SignatureAddOutputFunc(u_int32_t sid,
00271 void (*outputFunc)(Packet *, char *, void *, Event *),
00272 void *args)
00273 {
00274 OptTreeNode *optTreeNode = NULL;
00275 OutputFuncNode *outputFuncs = NULL;
00276
00277 if(!outputFunc)
00278 return SNORT_EINVAL;
00279
00280 if(!(optTreeNode = OptTreeNode_Search(sid)))
00281 {
00282 LogMessage("Unable to find OptTreeNode for SID %u\n", sid);
00283 return SNORT_ENOENT;
00284 }
00285
00286 if(!(outputFuncs = (OutputFuncNode *)calloc(1, sizeof(OutputFuncNode))))
00287 {
00288 LogMessage("Out of memory adding output function to SID %u\n", sid);
00289 return SNORT_ENOMEM;
00290 }
00291
00292 outputFuncs->func = outputFunc;
00293 outputFuncs->arg = args;
00294
00295 outputFuncs->next = optTreeNode->outputFuncs;
00296
00297 optTreeNode->outputFuncs = outputFuncs;
00298
00299 return SNORT_SUCCESS;
00300 }
00301
00302
00303
00304 static OptTreeNode *OptTreeNode_Search(u_int32_t sid)
00305 {
00306 RuleListNode *ruleListNode = RuleLists;
00307
00308 if(sid == 0)
00309 return NULL;
00310
00311 while(ruleListNode)
00312 {
00313 RuleTreeNode *ruleTreeNode;
00314 ListHead *listHead = ruleListNode->RuleList;
00315
00316 ruleTreeNode = listHead->IpList;
00317 while(ruleTreeNode)
00318 {
00319 OptTreeNode *optTreeNode;
00320
00321 optTreeNode = ruleTreeNode->down;
00322 while(optTreeNode)
00323 {
00324 if(optTreeNode->sigInfo.id == sid)
00325 return optTreeNode;
00326
00327 optTreeNode = optTreeNode->next;
00328 }
00329 ruleTreeNode = ruleTreeNode->right;
00330 }
00331
00332 ruleTreeNode = listHead->TcpList;
00333 while(ruleTreeNode)
00334 {
00335 OptTreeNode *optTreeNode;
00336
00337 optTreeNode = ruleTreeNode->down;
00338 while(optTreeNode)
00339 {
00340 if(optTreeNode->sigInfo.id == sid)
00341 return optTreeNode;
00342
00343 optTreeNode = optTreeNode->next;
00344 }
00345 ruleTreeNode = ruleTreeNode->right;
00346 }
00347
00348 ruleTreeNode = listHead->UdpList;
00349 while(ruleTreeNode)
00350 {
00351 OptTreeNode *optTreeNode;
00352
00353 optTreeNode = ruleTreeNode->down;
00354 while(optTreeNode)
00355 {
00356 if(optTreeNode->sigInfo.id == sid)
00357 return optTreeNode;
00358
00359 optTreeNode = optTreeNode->next;
00360 }
00361 ruleTreeNode = ruleTreeNode->right;
00362 }
00363
00364 ruleTreeNode = listHead->IcmpList;
00365 while(ruleTreeNode)
00366 {
00367 OptTreeNode *optTreeNode;
00368
00369 optTreeNode = ruleTreeNode->down;
00370 while(optTreeNode)
00371 {
00372 if(optTreeNode->sigInfo.id == sid)
00373 return optTreeNode;
00374
00375 optTreeNode = optTreeNode->next;
00376 }
00377 ruleTreeNode = ruleTreeNode->right;
00378 }
00379
00380 ruleListNode = ruleListNode->next;
00381 }
00382
00383 return NULL;
00384 }
00385
00386 int String2ULong(char *string, unsigned long *result)
00387 {
00388 unsigned long value;
00389 char *endptr;
00390 if(!string)
00391 return -1;
00392
00393 value = strtoul(string, &endptr, 10);
00394 if(*endptr != '\0')
00395 return -1;
00396
00397 *result = value;
00398
00399 return 0;
00400 }
00401
00402
00403 #endif
00404