1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
14 #ifdef PRELUDE_OUTPUT_ENABLED
16 #include <libprelude/prelude.h>
17 #include <libprelude/prelude-log.h>
18 #include <libprelude/idmef-message-print.h>
25 #define DEFAULT_ANALYZER_NAME "OSSEC"
26 #define ANALYZER_CLASS "Host IDS, File Integrity Checker, Log Analyzer"
27 #define ANALYZER_MODEL "Ossec"
28 #define ANALYZER_MANUFACTURER __site
29 #define ANALYZER_VERSION __version
31 /** OSSEC to prelude severity mapping. **/
32 static const char *(ossec2prelude_sev[]) = {"info", "info", "info", "info",
33 "low", "low", "low", "low",
34 "medium", "medium", "medium", "medium",
35 "high", "high", "high", "high", "high"
39 static prelude_client_t *prelude_client;
42 /*void prelude_idmef_debug(idmef_message_t *idmef)
47 prelude_io_set_file_io(pio, stderr);
48 idmef_message_print(idmef, pio);
49 prelude_io_destroy(pio);
53 add_idmef_object(idmef_message_t *msg, const char *object, const char *value)
63 ret = idmef_path_new_fast(&path, object);
68 ret = idmef_value_new_from_path(&val, path, value);
70 idmef_path_destroy(path);
74 ret = idmef_path_set(path, msg, val);
76 merror("%s: OSSEC2Prelude: IDMEF: Cannot add object '%s': %s.",
77 ARGV0, object, prelude_strerror(ret));
80 idmef_value_destroy(val);
81 idmef_path_destroy(path);
87 setup_analyzer(idmef_analyzer_t *analyzer)
90 prelude_string_t *string;
92 ret = idmef_analyzer_new_model(analyzer, &string);
96 prelude_string_set_constant(string, ANALYZER_MODEL);
98 ret = idmef_analyzer_new_class(analyzer, &string);
102 prelude_string_set_constant(string, ANALYZER_CLASS);
104 ret = idmef_analyzer_new_manufacturer(analyzer, &string);
108 prelude_string_set_constant(string, ANALYZER_MANUFACTURER);
110 ret = idmef_analyzer_new_version(analyzer, &string);
114 prelude_string_set_constant(string, ANALYZER_VERSION);
119 merror("%s: OSSEC2Prelude: %s: IDMEF error: %s.",
120 ARGV0, prelude_strsource(ret), prelude_strerror(ret));
125 void prelude_start(const char *profile, int argc, char **argv)
128 prelude_client = NULL;
130 ret = prelude_init(&argc, argv);
132 merror("%s: %s: Unable to initialize the Prelude library: %s.",
133 ARGV0, prelude_strsource(ret), prelude_strerror(ret));
137 ret = prelude_client_new(&prelude_client,
138 profile != NULL ? profile : DEFAULT_ANALYZER_NAME);
139 if (!prelude_client) {
140 merror("%s: %s: Unable to create a prelude client object: %s.",
141 ARGV0, prelude_strsource(ret), prelude_strerror(ret));
146 ret = setup_analyzer(prelude_client_get_analyzer(prelude_client));
148 merror("%s: %s: Unable to setup analyzer: %s",
149 ARGV0, prelude_strsource(ret), prelude_strerror(ret));
151 prelude_client_destroy(prelude_client,
152 PRELUDE_CLIENT_EXIT_STATUS_FAILURE);
157 ret = prelude_client_set_flags(prelude_client,
158 prelude_client_get_flags(prelude_client)
159 | PRELUDE_CLIENT_FLAGS_ASYNC_TIMER);
161 merror("%s: %s: Unable to set prelude client flags: %s.",
162 ARGV0, prelude_strsource(ret), prelude_strerror(ret));
165 /* Set uid and gid of ossec */
166 prelude_client_profile_set_uid(prelude_client_get_profile(prelude_client),
167 Privsep_GetUser(USER));
168 prelude_client_profile_set_gid(prelude_client_get_profile(prelude_client),
169 Privsep_GetGroup(GROUPGLOBAL));
171 ret = prelude_client_start(prelude_client);
173 merror("%s: %s: Unable to initialize prelude client: %s.",
174 ARGV0, prelude_strsource(ret), prelude_strerror(ret));
176 prelude_client_destroy(prelude_client,
177 PRELUDE_CLIENT_EXIT_STATUS_FAILURE);
185 static void FileAccess_PreludeLog(idmef_message_t *idmef,
186 const char *category,
187 const char *filename,
195 debug1("%s: DEBUG: filename = %s.", ARGV0, filename);
196 debug1("%s: DEBUG: category = %s.", ARGV0, category);
197 add_idmef_object(idmef, "alert.target(0).file(>>).name", filename);
198 add_idmef_object(idmef, "alert.target(0).file(-1).category", category);
202 add_idmef_object(idmef, "alert.target(0).file(-1).checksum(>>).algorithm", "MD5");
203 add_idmef_object(idmef, "alert.target(0).file(-1).checksum(-1).value", md5);
206 add_idmef_object(idmef, "alert.target(0).file(-1).checksum(>>).algorithm", "SHA1");
207 add_idmef_object(idmef, "alert.target(0).file(-1).checksum(-1).value", sha1);
212 debug1("%s: DEBUG: owner = %s.", ARGV0, owner);
213 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(>>).user_id.number", owner);
214 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).user_id.type", "user-privs");
217 /* Add the permissions */
218 if (perm & S_IWUSR) {
219 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "write");
220 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "delete");
222 if (perm & S_IXUSR) {
223 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "execute");
225 if (perm & S_IRUSR ) {
226 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "read");
228 if (perm & S_ISUID) {
229 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "executeAs");
234 /* Add the group owner */
236 debug1("%s: DEBUG: gowner = %s.", ARGV0, gowner);
237 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(>>).user_id.number", gowner);
238 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).user_id.type", "group-privs");
241 /* Add the permissions */
242 if (perm & S_IWGRP) {
243 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "write");
244 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "delete");
246 if (perm & S_IXGRP) {
247 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "execute");
249 if (perm & S_IRGRP ) {
250 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "read");
252 if (perm & S_ISGID) {
253 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "executeAs");
258 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(>>).user_id.type", "other-privs");
261 /* Add the permissions */
262 if (perm & S_IWOTH) {
263 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "write");
264 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "delete");
266 if (perm & S_IXOTH) {
267 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "execute");
269 if (perm & S_IROTH ) {
270 add_idmef_object(idmef, "alert.target(0).file(-1).file_access(-1).permission(>>)", "read");
276 void OS_PreludeLog(const Eventinfo *lf)
279 char _prelude_data[256];
281 idmef_message_t *idmef;
282 RuleInfoDetail *last_info_detail;
284 /* Generate prelude alert */
285 ret = idmef_message_new(&idmef);
287 merror("%s: OSSEC2Prelude: Cannot create IDMEF message", ARGV0);
291 add_idmef_object(idmef, "alert.assessment.impact.description",
292 lf->generated_rule->comment);
294 add_idmef_object(idmef, "alert.assessment.impact.severity",
295 (lf->generated_rule->level > 15) ? "high" :
296 ossec2prelude_sev[lf->generated_rule->level]);
298 add_idmef_object(idmef, "alert.assessment.impact.completion", "succeeded");
301 switch (*lf->action) {
302 /* discard, drop, deny, */
311 snprintf(_prelude_data, 256, "DROP: %s", lf->action);
319 snprintf(_prelude_data, 256, "CLOSED: %s", lf->action);
330 snprintf(_prelude_data, 256, "ALLOW: %s", lf->action);
333 snprintf(_prelude_data, 256, "%s", lf->action);
336 add_idmef_object(idmef, "alert.assessment.action(0).category", "3");
337 add_idmef_object(idmef, "alert.assessment.action(0).description", _prelude_data);
340 /* Begin Classification Infomations */
342 add_idmef_object(idmef, "alert.classification.text",
343 lf->generated_rule->comment);
345 /* The Common Vulnerabilities and Exposures (CVE) (http://www.cve.mitre.org/)
346 * infomation if present in the triggering rule
348 if (lf->generated_rule->cve) {
349 add_idmef_object(idmef, "alert.classification.reference(>>).origin", "cve");
350 add_idmef_object(idmef, "alert.classification.reference(-1).name", lf->generated_rule->cve);
352 snprintf(_prelude_data, 256, "CVE:%s", lf->generated_rule->cve);
353 add_idmef_object(idmef, "alert.classification.reference(-1).meaning", _prelude_data);
356 /* Rule sid is used to create a link to the rule on the OSSEC wiki */
357 if (lf->generated_rule->sigid) {
358 add_idmef_object(idmef, "alert.classification.reference(>>).origin", "vendor-specific");
360 snprintf(_prelude_data, 256, "Rule:%d", lf->generated_rule->sigid);
361 add_idmef_object(idmef, "alert.classification.reference(-1).name", _prelude_data);
362 add_idmef_object(idmef, "alert.classification.reference(-1).meaning", "OSSEC Rule Wiki Documentation");
364 snprintf(_prelude_data, 256, "http://www.ossec.net/wiki/Rule:%d",
365 lf->generated_rule->sigid);
366 add_idmef_object(idmef, "alert.classification.reference(-1).url", _prelude_data);
369 /* Extended Info Details */
370 for (last_info_detail = lf->generated_rule->info_details;
371 last_info_detail != NULL;
372 last_info_detail = last_info_detail->next) {
373 if (last_info_detail->type == RULEINFODETAIL_LINK) {
374 add_idmef_object(idmef, "alert.classification.reference(>>).origin", "vendor-specific");
376 snprintf(_prelude_data, 256, "Rule:%d link", lf->generated_rule->sigid);
377 add_idmef_object(idmef, "alert.classification.reference(-1).name", _prelude_data);
378 add_idmef_object(idmef, "alert.classification.reference(-1).url", last_info_detail->data);
380 } else if (last_info_detail->type == RULEINFODETAIL_TEXT) {
381 add_idmef_object(idmef, "alert.classification.reference(>>).origin", "vendor-specific");
383 snprintf(_prelude_data, 256, "Rule:%d info", lf->generated_rule->sigid);
384 add_idmef_object(idmef, "alert.classification.reference(-1).name", _prelude_data);
386 add_idmef_object(idmef, "alert.classification.reference(-1).meaning", last_info_detail->data);
389 switch (last_info_detail->type) {
390 case RULEINFODETAIL_CVE:
393 case RULEINFODETAIL_OSVDB:
396 case RULEINFODETAIL_BUGTRACK:
397 origin = "bugtraqid";
400 origin = "vendor-specific";
403 add_idmef_object(idmef, "alert.classification.reference(>>).origin", origin);
404 add_idmef_object(idmef, "alert.classification.reference(-1).name", last_info_detail->data);
408 /* Break up the list of groups on the "," boundary
409 * For each section create a prelude reference classification
410 * that points back to the the OSSEC wiki for more infomation.
412 if (lf->generated_rule->group) {
414 char new_generated_rule_group[256];
415 new_generated_rule_group[255] = '\0';
416 strncpy(new_generated_rule_group, lf->generated_rule->group, 255);
417 copy_group = strtok(new_generated_rule_group, ",");
419 add_idmef_object(idmef, "alert.classification.reference(>>).origin", "vendor-specific");
421 snprintf(_prelude_data, 256, "Group:%s", copy_group);
422 add_idmef_object(idmef, "alert.classification.reference(-1).name", _prelude_data);
424 add_idmef_object(idmef, "alert.classification.reference(-1).meaning", "OSSEC Group Wiki Documentation");
426 snprintf(_prelude_data, 256, "http://www.ossec.net/wiki/Group:%s",
428 add_idmef_object(idmef, "alert.classification.reference(-1).url", _prelude_data);
430 copy_group = strtok(NULL, ",");
433 } /* end classification block */
435 /* Begin Node infomation block */
437 /* Set source info */
438 add_idmef_object(idmef, "alert.source(0).spoofed", "no");
439 add_idmef_object(idmef, "alert.source(0).node.address(0).address",
441 add_idmef_object(idmef, "alert.source(0).service.port", lf->srcport);
444 add_idmef_object(idmef, "alert.source(0).user.user_id(0).name", lf->srcuser);
448 add_idmef_object(idmef, "alert.target(0).service.name", lf->program_name);
449 add_idmef_object(idmef, "alert.target(0).spoofed", "no");
452 add_idmef_object(idmef, "alert.target(0).node.address(0).address",
456 char new_prelude_target[256];
458 new_prelude_target[255] = '\0';
459 strncpy(new_prelude_target, lf->hostname, 255);
461 /* The messages can have the file, so we need to remove it
463 * enigma->/var/log/authlog
464 * (esqueleto2) 192.168.2.99->/var/log/squid/access.log
466 tmp_str = strstr(new_prelude_target, "->");
470 add_idmef_object(idmef, "alert.target(0).node.address(0).address",
473 add_idmef_object(idmef, "alert.target(0).service.name", lf->hostname);
474 add_idmef_object(idmef, "alert.target(0).service.port", lf->dstport);
477 add_idmef_object(idmef, "alert.target(0).user.category", "2");
478 add_idmef_object(idmef, "alert.target(0).user.user_id(0).name", lf->dstuser);
480 } /* end Node infomation block */
482 /* Set source file */
483 add_idmef_object(idmef, "alert.additional_data(0).type", "string");
484 add_idmef_object(idmef, "alert.additional_data(0).meaning", "Source file");
485 add_idmef_object(idmef, "alert.additional_data(0).data", lf->location);
488 add_idmef_object(idmef, "alert.additional_data(1).type", "string");
489 add_idmef_object(idmef, "alert.additional_data(1).meaning", "Full Log");
490 add_idmef_object(idmef, "alert.additional_data(1).data", lf->full_log);
492 idmef_alert_set_analyzer(idmef_message_get_alert(idmef),
494 (prelude_client_get_analyzer(prelude_client)),
496 debug1("%s: DEBUG: lf->filename = %s.", ARGV0, lf->filename);
498 FileAccess_PreludeLog(idmef,
506 FileAccess_PreludeLog(idmef,
514 debug1("%s: DEBUG: done with alert.target(0).file(1)", ARGV0);
517 debug1("%s: DEBUG: Sending IDMEF alert", ARGV0);
518 prelude_client_send_idmef(prelude_client, idmef);
519 debug1("%s: DEBUG: destroying IDMEF alert", ARGV0);
520 idmef_message_destroy(idmef);
523 #endif /* PRELUDE_OUTPUT_ENABLED */