00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include "config.h"
00026 #endif
00027
00028 #ifdef HAVE_LIBPRELUDE
00029
00030 #include <stdio.h>
00031 #include <sys/types.h>
00032 #include <sys/socket.h>
00033 #include <netinet/in.h>
00034 #include <arpa/inet.h>
00035
00036 #include <libprelude/prelude.h>
00037
00038 #include "event.h"
00039 #include "decode.h"
00040 #include "plugbase.h"
00041 #include "spo_plugbase.h"
00042 #include "parser.h"
00043 #include "debug.h"
00044 #include "util.h"
00045 #include "mstring.h"
00046
00047 #include "snort.h"
00048
00049 #define ANALYZER_CLASS "NIDS"
00050 #define ANALYZER_MODEL "Snort"
00051 #define ANALYZER_MANUFACTURER "http://www.snort.org"
00052
00053 #define DEFAULT_ANALYZER_NAME "snort"
00054
00055
00056 extern PV pv;
00057 extern OptTreeNode *otn_tmp;
00058
00059 static char *init_args = NULL;
00060 static unsigned int info_priority = 4;
00061 static unsigned int low_priority = 3;
00062 static unsigned int mid_priority = 2;
00063 static prelude_bool_t initialized = FALSE;
00064
00065
00066 static int setup_analyzer(idmef_analyzer_t *analyzer)
00067 {
00068 int ret;
00069 prelude_string_t *string;
00070
00071 ret = idmef_analyzer_new_model(analyzer, &string);
00072 if ( ret < 0 )
00073 return ret;
00074 prelude_string_set_constant(string, ANALYZER_MODEL);
00075
00076 ret = idmef_analyzer_new_class(analyzer, &string);
00077 if ( ret < 0 )
00078 return ret;
00079 prelude_string_set_constant(string, ANALYZER_CLASS);
00080
00081 ret = idmef_analyzer_new_manufacturer(analyzer, &string);
00082 if ( ret < 0 )
00083 return ret;
00084 prelude_string_set_constant(string, ANALYZER_MANUFACTURER);
00085
00086 ret = idmef_analyzer_new_version(analyzer, &string);
00087 if ( ret < 0 )
00088 return ret;
00089 prelude_string_set_constant(string, VERSION);
00090
00091 return 0;
00092 }
00093
00094
00095
00096 static idmef_reference_origin_t reference_to_origin(const char *name)
00097 {
00098 int i, ret;
00099 struct {
00100 const char *name;
00101 idmef_reference_origin_t origin;
00102 } tbl[] = {
00103 { "cve", IDMEF_REFERENCE_ORIGIN_CVE },
00104 { "bugtraq", IDMEF_REFERENCE_ORIGIN_BUGTRAQID },
00105 { "osvdb", IDMEF_REFERENCE_ORIGIN_OSVDB },
00106 { NULL, 0 }
00107 };
00108
00109 for ( i = 0; tbl[i].name; i++ ) {
00110 ret = strcmp(tbl[i].name, name);
00111 if ( ret == 0 )
00112 return tbl[i].origin;
00113 }
00114
00115 return IDMEF_REFERENCE_ORIGIN_VENDOR_SPECIFIC;
00116 }
00117
00118
00119
00120 static int event_to_source_target(Packet *p, idmef_alert_t *alert)
00121 {
00122 int ret;
00123 idmef_node_t *node;
00124 idmef_source_t *source;
00125 idmef_target_t *target;
00126 idmef_address_t *address;
00127 idmef_service_t *service;
00128 prelude_string_t *string;
00129 static char saddr[128], daddr[128];
00130
00131 if ( !p )
00132 return 0;
00133
00134 if ( ! p->iph )
00135 return 0;
00136
00137 ret = idmef_alert_new_source(alert, &source, -1);
00138 if ( ret < 0 )
00139 return ret;
00140
00141 ret = idmef_source_new_service(source, &service);
00142 if ( ret < 0 )
00143 return ret;
00144
00145 if ( p->tcph || p->udph )
00146 idmef_service_set_port(service, p->sp);
00147
00148 idmef_service_set_ip_version(service, IP_VER(p->iph));
00149 idmef_service_set_iana_protocol_number(service, p->iph->ip_proto);
00150
00151 ret = idmef_source_new_node(source, &node);
00152 if ( ret < 0 )
00153 return ret;
00154
00155 ret = idmef_node_new_address(node, &address, -1);
00156 if ( ret < 0 )
00157 return ret;
00158
00159 ret = idmef_address_new_address(address, &string);
00160 if ( ret < 0 )
00161 return ret;
00162
00163 snprintf(saddr, sizeof(saddr), "%s", inet_ntoa(p->iph->ip_src));
00164 prelude_string_set_ref(string, saddr);
00165
00166 ret = idmef_alert_new_target(alert, &target, -1);
00167 if ( ret < 0 )
00168 return ret;
00169
00170 ret = idmef_target_new_service(target, &service);
00171 if ( ! ret < 0 )
00172 return ret;
00173
00174 if ( p->tcph || p->udph )
00175 idmef_service_set_port(service, p->dp);
00176
00177 idmef_service_set_ip_version(service, IP_VER(p->iph));
00178 idmef_service_set_iana_protocol_number(service, p->iph->ip_proto);
00179
00180 ret = idmef_target_new_node(target, &node);
00181 if ( ret < 0 )
00182 return ret;
00183
00184 ret = idmef_node_new_address(node, &address, -1);
00185 if ( ret < 0 )
00186 return ret;
00187
00188 ret = idmef_address_new_address(address, &string);
00189 if ( ret < 0 )
00190 return ret;
00191
00192 snprintf(daddr, sizeof(daddr), "%s", inet_ntoa(p->iph->ip_dst));
00193 prelude_string_set_ref(string, daddr);
00194
00195 return 0;
00196 }
00197
00198
00199
00200 static int add_byte_data(idmef_alert_t *alert, const char *meaning, const unsigned char *data, size_t size)
00201 {
00202 int ret;
00203 prelude_string_t *str;
00204 idmef_additional_data_t *ad;
00205
00206 if ( ! data || ! size )
00207 return 0;
00208
00209 ret = idmef_alert_new_additional_data(alert, &ad, -1);
00210 if ( ret < 0 )
00211 return ret;
00212
00213 ret = idmef_additional_data_set_byte_string_ref(ad, data, size);
00214 if ( ret < 0 ) {
00215 ErrorMessage("%s: error setting byte string data: %s.\n",
00216 prelude_strsource(ret), prelude_strerror(ret));
00217 return -1;
00218 }
00219
00220 ret = idmef_additional_data_new_meaning(ad, &str);
00221 if ( ret < 0 ) {
00222 ErrorMessage("%s: error creating additional-data meaning: %s.\n",
00223 prelude_strsource(ret), prelude_strerror(ret));
00224 return -1;
00225 }
00226
00227 ret = prelude_string_set_ref(str, meaning);
00228 if ( ret < 0 ) {
00229 ErrorMessage("%s: error setting byte string data meaning: %s.\n",
00230 prelude_strsource(ret), prelude_strerror(ret));
00231 }
00232
00233 return -1;
00234 }
00235
00236
00237
00238 static int add_int_data(idmef_alert_t *alert, const char *meaning, uint32_t data)
00239 {
00240 int ret;
00241 prelude_string_t *str;
00242 idmef_additional_data_t *ad;
00243
00244 ret = idmef_alert_new_additional_data(alert, &ad, -1);
00245 if ( ret < 0 )
00246 return ret;
00247
00248 idmef_additional_data_set_integer(ad, data);
00249
00250 ret = idmef_additional_data_new_meaning(ad, &str);
00251 if ( ret < 0 ) {
00252 ErrorMessage("%s: error creating additional-data meaning: %s.\n",
00253 prelude_strsource(ret), prelude_strerror(ret));
00254 return -1;
00255 }
00256
00257 ret = prelude_string_set_ref(str, meaning);
00258 if ( ret < 0 ) {
00259 ErrorMessage("%s: error setting integer data meaning: %s.\n",
00260 prelude_strsource(ret), prelude_strerror(ret));
00261 return -1;
00262 }
00263
00264 return 0;
00265 }
00266
00267
00268
00269
00270 static int packet_to_data(Packet *p, Event *event, idmef_alert_t *alert)
00271 {
00272 if ( !p )
00273 return 0;
00274
00275 add_int_data(alert, "sid", event->sig_id);
00276
00277 if ( p->iph ) {
00278 add_int_data(alert, "ip_mf", p->mf);
00279 add_int_data(alert, "ip_df", p->df);
00280 add_int_data(alert, "ip_rf", p->rf);
00281 add_int_data(alert, "ip_off", p->frag_offset);
00282 add_int_data(alert, "ip_hlen", IP_HLEN(p->iph));
00283 add_int_data(alert, "ip_tos", p->iph->ip_tos);
00284 add_int_data(alert, "ip_len", ntohs(p->iph->ip_len));
00285 add_int_data(alert, "ip_id", ntohs(p->iph->ip_id));
00286 add_int_data(alert, "ip_flags", p->frag_flag);
00287 add_int_data(alert, "ip_off", ntohs(p->frag_offset));
00288 add_int_data(alert, "ip_ttl", p->iph->ip_ttl);
00289 add_int_data(alert, "ip_proto", p->iph->ip_proto);
00290 add_int_data(alert, "ip_csum", ntohs(p->iph->ip_csum));
00291 }
00292
00293 if ( p->tcph ) {
00294 add_int_data(alert, "th_seq", ntohl(p->tcph->th_seq));
00295 add_int_data(alert, "th_ack", ntohl(p->tcph->th_ack));
00296 add_int_data(alert, "tcp_off", TCP_OFFSET(p->tcph));
00297 add_int_data(alert, "tcp_res", TCP_X2(p->tcph));
00298 add_int_data(alert, "tcp_flags", p->tcph->th_flags);
00299 add_int_data(alert, "tcp_win", ntohs(p->tcph->th_win));
00300 add_int_data(alert, "tcp_sum", ntohs(p->tcph->th_sum));
00301 add_int_data(alert, "tcp_urp", ntohs(p->tcph->th_urp));
00302 }
00303
00304 else if ( p->udph ) {
00305 add_int_data(alert, "udp_len", ntohl(p->udph->uh_len));
00306 add_int_data(alert, "udp_chk", ntohl(p->udph->uh_chk));
00307 }
00308
00309 add_byte_data(alert, "payload", p->data, p->dsize);
00310
00311 return 0;
00312 }
00313
00314
00315
00316 static int event_to_impact(Event *event, idmef_alert_t *alert)
00317 {
00318 int ret;
00319 ClassType *classtype;
00320 prelude_string_t *str;
00321 idmef_impact_t *impact;
00322 idmef_assessment_t *assessment;
00323 idmef_impact_severity_t severity;
00324
00325 ret = idmef_alert_new_assessment(alert, &assessment);
00326 if ( ret < 0 )
00327 return ret;
00328
00329 ret = idmef_assessment_new_impact(assessment, &impact);
00330 if ( ret < 0 )
00331 return ret;
00332
00333 if ( event->priority < mid_priority )
00334 severity = IDMEF_IMPACT_SEVERITY_HIGH;
00335
00336 else if ( event->priority < low_priority )
00337 severity = IDMEF_IMPACT_SEVERITY_MEDIUM;
00338
00339 else if ( event->priority < info_priority )
00340 severity = IDMEF_IMPACT_SEVERITY_LOW;
00341
00342 else severity = IDMEF_IMPACT_SEVERITY_INFO;
00343
00344 idmef_impact_set_severity(impact, severity);
00345
00346 if ( ! otn_tmp )
00347 return 0;
00348
00349 classtype = otn_tmp->sigInfo.classType;
00350 if ( classtype ) {
00351 ret = idmef_impact_new_description(impact, &str);
00352 if ( ret < 0 )
00353 return ret;
00354
00355 prelude_string_set_ref(str, classtype->name);
00356 }
00357
00358 return 0;
00359 }
00360
00361
00362
00363
00364 static int event_to_reference(Event *event, idmef_classification_t *class)
00365 {
00366 int ret;
00367 ReferenceNode *refs;
00368 prelude_string_t *str;
00369 idmef_reference_t *ref;
00370 ReferenceSystemNode *system;
00371
00372 ret = idmef_classification_new_ident(class, &str);
00373 if ( ret < 0 )
00374 return ret;
00375
00376 ret = prelude_string_sprintf(str, "%u", event->sig_id);
00377 if ( ret < 0 )
00378 return ret;
00379
00380
00381
00382
00383 if ( ! otn_tmp )
00384 return 0;
00385
00386 for ( refs = otn_tmp->sigInfo.refs; refs != NULL; refs = refs->next ) {
00387
00388 system = refs->system;
00389 if ( ! system )
00390 continue;
00391
00392 ret = idmef_classification_new_reference(class, &ref, -1);
00393 if ( ret < 0 )
00394 return ret;
00395
00396 ret = idmef_reference_new_name(ref, &str);
00397 if ( ret < 0 )
00398 return ret;
00399
00400 idmef_reference_set_origin(ref, reference_to_origin(system->name));
00401 if ( idmef_reference_get_origin(ref) != IDMEF_REFERENCE_ORIGIN_VENDOR_SPECIFIC )
00402 prelude_string_set_ref(str, refs->id);
00403 else
00404 prelude_string_set_constant(str, "url");
00405
00406 ret = idmef_reference_new_url(ref, &str);
00407 if ( ret < 0 )
00408 return ret;
00409
00410 prelude_string_sprintf(str, "%s%s", system->url, refs->id);
00411 }
00412
00413 return 0;
00414 }
00415
00416
00417
00418 void snort_alert_prelude(Packet *p, char *msg, void *data, Event *event)
00419 {
00420 int ret;
00421 idmef_time_t *time;
00422 idmef_alert_t *alert;
00423 prelude_string_t *str;
00424 idmef_message_t *idmef;
00425 idmef_classification_t *class;
00426 prelude_client_t *client = data;
00427
00428 if ( !p )
00429 return;
00430
00431 ret = idmef_message_new(&idmef);
00432 if ( ret < 0 )
00433 return;
00434
00435 ret = idmef_message_new_alert(idmef, &alert);
00436 if ( ret < 0 )
00437 goto err;
00438
00439 ret = idmef_alert_new_classification(alert, &class);
00440 if ( ret < 0 )
00441 goto err;
00442
00443 ret = idmef_classification_new_text(class, &str);
00444 if ( ret < 0 )
00445 goto err;
00446
00447 prelude_string_set_ref(str, msg);
00448
00449 ret = event_to_impact(event, alert);
00450 if ( ret < 0 )
00451 goto err;
00452
00453 ret = event_to_reference(event, class);
00454 if ( ret < 0 )
00455 goto err;
00456
00457 ret = event_to_source_target(p, alert);
00458 if ( ret < 0 )
00459 goto err;
00460
00461 ret = packet_to_data(p, event, alert);
00462 if ( ret < 0 )
00463 goto err;
00464
00465 ret = idmef_alert_new_detect_time(alert, &time);
00466 if ( ret < 0 )
00467 goto err;
00468 idmef_time_set_from_timeval(time, &p->pkth->ts);
00469
00470 ret = idmef_time_new_from_gettimeofday(&time);
00471 if ( ret < 0 )
00472 goto err;
00473 idmef_alert_set_create_time(alert, time);
00474
00475 idmef_alert_set_analyzer(alert, idmef_analyzer_ref(prelude_client_get_analyzer(client)), 0);
00476 prelude_client_send_idmef(client, idmef);
00477
00478 err:
00479 idmef_message_destroy(idmef);
00480 }
00481
00482
00483
00484 void snort_alert_prelude_clean_exit(int signal, void *data)
00485 {
00486
00487 }
00488
00489
00490 void snort_alert_prelude_restart(int signal, void *data)
00491 {
00492
00493
00494
00495
00496
00497
00498
00499
00500 }
00501
00502
00503
00504 static void parse_args(char *args, char **profile)
00505 {
00506 int i, tokens, ret;
00507 char **args_table, *value, *key;
00508
00509 args_table = mSplit(args, " ", 4, &tokens, '\\');
00510 for ( i = 0; i < tokens; i++ ) {
00511
00512 key = args_table[i];
00513 strtok(key, "=");
00514
00515 value = strtok(NULL, "");
00516 if ( ! value )
00517 FatalError("spo_alert_prelude: missing value for keyword '%s'.\n", key);
00518
00519 ret = strcasecmp("profile", key);
00520 if ( ret == 0 ) {
00521 if ( *profile )
00522 free(*profile);
00523
00524 *profile = strdup(value);
00525 continue;
00526 }
00527
00528 ret = strcasecmp("info", key);
00529 if ( ret == 0 ) {
00530 info_priority = atoi(value);
00531 continue;
00532 }
00533
00534 ret = strcasecmp("low", key);
00535 if ( ret == 0 ) {
00536 low_priority = atoi(value);
00537 continue;
00538 }
00539
00540 ret = strcasecmp("medium", key);
00541 if ( ret == 0 ) {
00542 mid_priority = atoi(value);
00543 continue;
00544 }
00545
00546 FatalError("spo_alert_prelude: Invalid parameter found: '%s'.\n", key);
00547 }
00548
00549 mSplitFree(&args_table, tokens);
00550 }
00551
00552
00553 void AlertPreludeSetupAfterSetuid(void)
00554 {
00555 int ret;
00556 char *profile = NULL;
00557 prelude_client_t *client;
00558 prelude_client_flags_t flags;
00559
00560 if ( ! initialized )
00561 return;
00562
00563 parse_args(init_args, &profile);
00564 free(init_args);
00565
00566 ret = prelude_thread_init(NULL);
00567 if ( ret < 0 )
00568 FatalError("%s: Unable to initialize the Prelude thread subsystem: %s.\n",
00569 prelude_strsource(ret), prelude_strerror(ret));
00570
00571 ret = prelude_init(NULL, NULL);
00572 if ( ret < 0 )
00573 FatalError("%s: Unable to initialize the Prelude library: %s.\n",
00574 prelude_strsource(ret), prelude_strerror(ret));
00575
00576 ret = prelude_client_new(&client, profile ? profile : DEFAULT_ANALYZER_NAME);
00577 if ( profile )
00578 free(profile);
00579
00580 if ( ret < 0 )
00581 FatalError("%s: Unable to create a prelude client object: %s.\n",
00582 prelude_strsource(ret), prelude_strerror(ret));
00583
00584
00585 flags = PRELUDE_CLIENT_FLAGS_ASYNC_SEND|PRELUDE_CLIENT_FLAGS_ASYNC_TIMER;
00586
00587 ret = prelude_client_set_flags(client, prelude_client_get_flags(client) | flags);
00588 if ( ret < 0 )
00589 FatalError("%s: Unable to set asynchronous send and timer: %s.\n",
00590 prelude_strsource(ret), prelude_strerror(ret));
00591
00592
00593 setup_analyzer(prelude_client_get_analyzer(client));
00594
00595 ret = prelude_client_start(client);
00596 if ( ret < 0 ) {
00597 if ( prelude_client_is_setup_needed(ret) )
00598 prelude_client_print_setup_error(client);
00599
00600 FatalError("%s: Unable to initialize prelude client: %s.\n",
00601 prelude_strsource(ret), prelude_strerror(ret));
00602 }
00603
00604 AddFuncToOutputList(snort_alert_prelude, NT_OUTPUT_ALERT, client);
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 }
00623
00624
00625 void snort_alert_prelude_init(unsigned char *args)
00626 {
00627
00628
00629
00630 if ( args )
00631 init_args = strdup((char *) args);
00632
00633 initialized = TRUE;
00634 }
00635
00636
00637 void AlertPreludeSetup(void)
00638 {
00639 RegisterOutputPlugin("alert_prelude", NT_OUTPUT_ALERT, snort_alert_prelude_init);
00640 }
00641
00642
00643 #endif