-/* @(#) $Id$ */
-
/* Copyright (C) 2009 Trend Micro Inc.
* All rights reserved.
*
* and/or modify it under the terms of the GNU General Public
* License (version 2) as published by the FSF - Free Software
* Foundation
- *
- * License details at the LICENSE file included with OSSEC or
- * online at: http://www.ossec.net/en/licensing.html
*/
-
#include "csyslogd.h"
+#include "cJSON.h"
#include "config/config.h"
#include "os_net/os_net.h"
-
-
-
-/** int OS_Alert_SendSyslog
- * Sends an alert via syslog.
- * Returns 1 on success or 0 on error.
+/* Send an alert via syslog
+ * Returns 1 on success or 0 on error
*/
-int OS_Alert_SendSyslog(alert_data *al_data, SyslogConfig *syslog_config)
+int OS_Alert_SendSyslog(alert_data *al_data, const SyslogConfig *syslog_config)
{
char *tstamp;
- char user_msg[256];
- char srcip_msg[256];
-
- char syslog_msg[OS_SIZE_2048 +1];
+ char *hostname;
+ char syslog_msg[OS_SIZE_2048];
-
- /* Invalid socket. */
- if(syslog_config->socket < 0)
- {
- return(0);
+ /* Invalid socket */
+ if (syslog_config->socket < 0) {
+ return (0);
}
-
-
- /* Clearing the memory before insert */
- memset(syslog_msg, '\0', OS_SIZE_2048 +1);
+ /* Clear the memory before insert */
+ memset(syslog_msg, '\0', OS_SIZE_2048);
- /* Looking if location is set */
- if(syslog_config->location)
- {
- if(!OSMatch_Execute(al_data->location,
- strlen(al_data->location),
- syslog_config->location))
- {
- return(0);
+ /* Look if location is set */
+ if (syslog_config->location) {
+ if (!OSMatch_Execute(al_data->location,
+ strlen(al_data->location),
+ syslog_config->location)) {
+ return (0);
}
}
-
- /* Looking for the level */
- if(syslog_config->level)
- {
- if(al_data->level < syslog_config->level)
- {
- return(0);
+ /* Look for the level */
+ if (syslog_config->level) {
+ if (al_data->level < syslog_config->level) {
+ return (0);
}
}
-
- /* Looking for rule id */
- if(syslog_config->rule_id)
- {
+ /* Look for rule id */
+ if (syslog_config->rule_id) {
int id_i = 0;
- while(syslog_config->rule_id[id_i] != 0)
- {
- if(syslog_config->rule_id[id_i] == al_data->rule)
- {
+ while (syslog_config->rule_id[id_i] != 0) {
+ if (syslog_config->rule_id[id_i] == al_data->rule) {
break;
}
id_i++;
}
-
/* If we found, id is going to be a valid rule */
- if(!syslog_config->rule_id[id_i])
- {
- return(0);
+ if (!syslog_config->rule_id[id_i]) {
+ return (0);
}
}
-
- /* Looking for the group */
- if(syslog_config->group)
- {
- if(!OSMatch_Execute(al_data->group,
- strlen(al_data->group),
- syslog_config->group))
- {
- return(0);
+ /* Look for the group */
+ if (syslog_config->group) {
+ if (!OSMatch_Execute(al_data->group,
+ strlen(al_data->group),
+ syslog_config->group)) {
+ return (0);
}
}
-
- /* Fixing the timestamp to be syslog compatible.
+ /* Fix the timestamp to be syslog compatible
* We have 2008 Jul 10 10:11:23
* Should be: Jul 10 10:11:23
*/
tstamp = al_data->date;
- if(strlen(al_data->date) > 14)
- {
- tstamp+=5;
+ if (strlen(al_data->date) > 14) {
+ tstamp += 5;
- /* Fixing first digit if the day is < 10 */
- if(tstamp[4] == '0')
+ /* Fix first digit if the day is < 10 */
+ if (tstamp[4] == '0') {
tstamp[4] = ' ';
+ }
}
-
-
- /* Adding source ip. */
- if(!al_data->srcip ||
- ((al_data->srcip[0] == '(') &&
- (al_data->srcip[1] == 'n') &&
- (al_data->srcip[2] == 'o')))
- {
- srcip_msg[0] = '\0';
- }
- else
- {
- snprintf(srcip_msg, 255, " srcip: %s;", al_data->srcip);
+
+ if (syslog_config->use_fqdn) {
+ hostname = __shost_long;
+ } else {
+ hostname = __shost;
}
+ /* Insert data */
+ if (syslog_config->format == DEFAULT_CSYSLOG) {
+ /* Build syslog message */
+ snprintf(syslog_msg, OS_SIZE_2048,
+ "<%u>%s %s ossec: Alert Level: %u; Rule: %u - %s; Location: %s;",
+ syslog_config->priority, tstamp, hostname,
+ al_data->level,
+ al_data->rule, al_data->comment,
+ al_data->location
+ );
+ field_add_string(syslog_msg, OS_SIZE_2048, " classification: %s;", al_data->group );
+ field_add_string(syslog_msg, OS_SIZE_2048, " srcip: %s;", al_data->srcip );
+#ifdef LIBGEOIP_ENABLED
+ field_add_string(syslog_msg, OS_SIZE_2048, " srccity: %s;", al_data->srcgeoip );
+ field_add_string(syslog_msg, OS_SIZE_2048, " dstcity: %s;", al_data->dstgeoip );
+#endif
+ field_add_string(syslog_msg, OS_SIZE_2048, " dstip: %s;", al_data->dstip );
+ field_add_string(syslog_msg, OS_SIZE_2048, " user: %s;", al_data->user );
+ field_add_string(syslog_msg, OS_SIZE_2048, " Previous MD5: %s;", al_data->old_md5 );
+ field_add_string(syslog_msg, OS_SIZE_2048, " Current MD5: %s;", al_data->new_md5 );
+ field_add_string(syslog_msg, OS_SIZE_2048, " Previous SHA1: %s;", al_data->old_sha1 );
+ field_add_string(syslog_msg, OS_SIZE_2048, " Current SHA1: %s;", al_data->new_sha1 );
+ /* "9/19/2016 - Sivakumar Nellurandi - parsing additions" */
+ field_add_string(syslog_msg, OS_SIZE_2048, " Size changed: from %s;", al_data->file_size );
+ field_add_string(syslog_msg, OS_SIZE_2048, " User ownership: was %s;", al_data->owner_chg );
+ field_add_string(syslog_msg, OS_SIZE_2048, " Group ownership: was %s;", al_data->group_chg );
+ field_add_string(syslog_msg, OS_SIZE_2048, " Permissions changed: from %s;", al_data->perm_chg );
+ /* "9/19/2016 - Sivakumar Nellurandi - parsing additions" */
+ field_add_truncated(syslog_msg, OS_SIZE_2048, " %s", al_data->log[0], 2 );
+ } else if (syslog_config->format == CEF_CSYSLOG) {
+ snprintf(syslog_msg, OS_SIZE_2048,
+ "<%u>%s CEF:0|%s|%s|%s|%u|%s|%u|dvc=%s cs1=%s cs1Label=Location",
+ syslog_config->priority,
+ tstamp,
+ __author,
+ __ossec_name,
+ __version,
+ al_data->rule,
+ al_data->comment,
+ (al_data->level > 10) ? 10 : al_data->level,
+ hostname, al_data->location);
+ field_add_string(syslog_msg, OS_SIZE_2048, " classification=%s", al_data->group );
+ field_add_string(syslog_msg, OS_SIZE_2048, " src=%s", al_data->srcip );
+ field_add_int(syslog_msg, OS_SIZE_2048, " dpt=%d", al_data->dstport );
+ field_add_int(syslog_msg, OS_SIZE_2048, " spt=%d", al_data->srcport );
+ field_add_string(syslog_msg, OS_SIZE_2048, " fname=%s", al_data->filename );
+ field_add_string(syslog_msg, OS_SIZE_2048, " dhost=%s", al_data->dstip );
+ field_add_string(syslog_msg, OS_SIZE_2048, " shost=%s", al_data->srcip );
+ field_add_string(syslog_msg, OS_SIZE_2048, " suser=%s", al_data->user );
+ field_add_string(syslog_msg, OS_SIZE_2048, " dst=%s", al_data->dstip );
+#ifdef LIBGEOIP_ENABLED
+ field_add_string(syslog_msg, OS_SIZE_2048, " cs4Label=SrcCity cs4=%s", al_data->srcgeoip );
+ field_add_string(syslog_msg, OS_SIZE_2048, " cs5Label=DstCity cs5=%s", al_data->dstgeoip );
+#endif
+ field_add_string(syslog_msg, OS_SIZE_2048, " suser=%s", al_data->user );
+ field_add_string(syslog_msg, OS_SIZE_2048, " dst=%s", al_data->dstip );
+ field_add_truncated(syslog_msg, OS_SIZE_2048, " msg=%s", al_data->log[0], 2 );
+ if (al_data->new_md5 && al_data->new_sha1) {
+ field_add_string(syslog_msg, OS_SIZE_2048, " cs2Label=OldMD5 cs2=%s", al_data->old_md5);
+ field_add_string(syslog_msg, OS_SIZE_2048, " cs3Label=NewMD5 cs3=%s", al_data->new_md5);
+ field_add_string(syslog_msg, OS_SIZE_2048, " oldFileHash=%s", al_data->old_sha1 );
+ field_add_string(syslog_msg, OS_SIZE_2048, " fhash=%s", al_data->new_sha1 );
+ field_add_string(syslog_msg, OS_SIZE_2048, " fileHash=%s", al_data->new_sha1 );
+ }
+ } else if (syslog_config->format == JSON_CSYSLOG) {
+ /* Build a JSON Object for logging */
+ cJSON *root;
+ char *json_string;
+ root = cJSON_CreateObject();
+
+ /* Data guaranteed to be there */
+ cJSON_AddNumberToObject(root, "crit", al_data->level);
+ cJSON_AddNumberToObject(root, "id", al_data->rule);
+ cJSON_AddStringToObject(root, "component", al_data->location);
+
+ /* Rule Meta Data */
+ if (al_data->group) {
+ cJSON_AddStringToObject(root, "classification", al_data->group);
+ }
+ if (al_data->comment) {
+ cJSON_AddStringToObject(root, "description", al_data->comment);
+ }
- /* Adding username. */
- if(!al_data->user ||
- ((al_data->user[0] == '(') &&
- (al_data->user[1] == 'n') &&
- (al_data->user[2] == 'o')))
- {
- user_msg[0] = '\0';
- }
- else
- {
- snprintf(user_msg, 255, " user: %s;", al_data->user);
- }
+ /* Raw log message generating event */
+ if (al_data->log && al_data->log[0]) {
+ cJSON_AddStringToObject(root, "message", al_data->log[0]);
+ }
+ /* Add data if it exists */
+ if (al_data->user) {
+ cJSON_AddStringToObject(root, "acct", al_data->user);
+ }
+ if (al_data->srcip) {
+ cJSON_AddStringToObject(root, "src_ip", al_data->srcip);
+ }
+ if (al_data->srcport) {
+ cJSON_AddNumberToObject(root, "src_port", al_data->srcport);
+ }
+ if (al_data->dstip) {
+ cJSON_AddStringToObject(root, "dst_ip", al_data->dstip);
+ }
+ if (al_data->dstport) {
+ cJSON_AddNumberToObject(root, "dst_port", al_data->dstport);
+ }
+ if (al_data->filename) {
+ cJSON_AddStringToObject(root, "file", al_data->filename);
+ }
+ if (al_data->old_md5) {
+ cJSON_AddStringToObject(root, "md5_old", al_data->old_md5);
+ }
+ if (al_data->new_md5) {
+ cJSON_AddStringToObject(root, "md5_new", al_data->new_md5);
+ }
+ if (al_data->old_sha1) {
+ cJSON_AddStringToObject(root, "sha1_old", al_data->old_sha1);
+ }
+ if (al_data->new_sha1) {
+ cJSON_AddStringToObject(root, "sha1_new", al_data->new_sha1);
+ }
+#ifdef LIBGEOIP_ENABLED
+ if (al_data->srcgeoip) {
+ cJSON_AddStringToObject(root, "src_city", al_data->srcgeoip);
+ }
+ if (al_data->dstgeoip) {
+ cJSON_AddStringToObject(root, "dst_city", al_data->dstgeoip);
+ }
+#endif
- /* Inserting data */
- if(syslog_config->format == DEFAULT_CSYSLOG)
- {
- /* Building syslog message. */
+ /* Create the JSON string */
+ json_string = cJSON_PrintUnformatted(root);
+
+ /* Create the syslog message */
snprintf(syslog_msg, OS_SIZE_2048,
- "<%d>%s %s ossec: Alert Level: %d; Rule: %d - %s; "
- "Location: %s;%s%s %s",
- syslog_config->priority, tstamp, __shost,
- al_data->level, al_data->rule, al_data->comment,
- al_data->location,
-
- /* Source ip. */
- srcip_msg,
- user_msg,
- al_data->log[0]);
- }
+ "<%u>%s %s ossec: %s",
+
+ /* syslog header */
+ syslog_config->priority, tstamp, hostname,
+
+ /* JSON Encoded Data */
+ json_string
+ );
+ /* Clean up the memory for the JSON structure */
+ free(json_string);
+ cJSON_Delete(root);
+ } else if (syslog_config->format == SPLUNK_CSYSLOG) {
+ /* Build a Splunk Style Key/Value string for logging */
+ snprintf(syslog_msg, OS_SIZE_2048,
+ "<%u>%s %s ossec: crit=%u id=%u description=\"%s\" component=\"%s\",",
+
+ /* syslog header */
+ syslog_config->priority, tstamp, hostname,
+
+ /* OSSEC metadata */
+ al_data->level, al_data->rule, al_data->comment,
+ al_data->location
+ );
+ /* Event specifics */
+ field_add_string(syslog_msg, OS_SIZE_2048, " classification=\"%s\",", al_data->group );
+
+ if ( field_add_string(syslog_msg, OS_SIZE_2048, " src_ip=\"%s\",", al_data->srcip ) > 0 ) {
+ field_add_int(syslog_msg, OS_SIZE_2048, " src_port=%d,", al_data->srcport );
+ }
+
+#ifdef LIBGEOIP_ENABLED
+ field_add_string(syslog_msg, OS_SIZE_2048, " src_city=\"%s\",", al_data->srcgeoip );
+ field_add_string(syslog_msg, OS_SIZE_2048, " dst_city=\"%s\",", al_data->dstgeoip );
+#endif
+
+ if ( field_add_string(syslog_msg, OS_SIZE_2048, " dst_ip=\"%s\",", al_data->dstip ) > 0 ) {
+ field_add_int(syslog_msg, OS_SIZE_2048, " dst_port=%d,", al_data->dstport );
+ }
+ field_add_string(syslog_msg, OS_SIZE_2048, " file=\"%s\",", al_data->filename );
+ field_add_string(syslog_msg, OS_SIZE_2048, " acct=\"%s\",", al_data->user );
+ field_add_string(syslog_msg, OS_SIZE_2048, " md5_old=\"%s\",", al_data->old_md5 );
+ field_add_string(syslog_msg, OS_SIZE_2048, " md5_new=\"%s\",", al_data->new_md5 );
+ field_add_string(syslog_msg, OS_SIZE_2048, " sha1_old=\"%s\",", al_data->old_sha1 );
+ field_add_string(syslog_msg, OS_SIZE_2048, " sha1_new=\"%s\",", al_data->new_sha1 );
+ /* Message */
+ field_add_truncated(syslog_msg, OS_SIZE_2048, " message=\"%s\"", al_data->log[0], 2 );
+ }
OS_SendUDPbySize(syslog_config->socket, strlen(syslog_msg), syslog_msg);
-
- return(1);
+ return (1);
}
-
-/* EOF */