Imported Upstream version 2.7
[ossec-hids.git] / src / os_csyslogd / alert.c
index cef1454..f271cb5 100755 (executable)
@@ -1,4 +1,5 @@
-/* @(#) $Id$ */
+/* @(#) $Id: ./src/os_csyslogd/alert.c, 2011/09/08 dcid Exp $
+ */
 
 /* Copyright (C) 2009 Trend Micro Inc.
  * All rights reserved.
 #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.
 int OS_Alert_SendSyslog(alert_data *al_data, SyslogConfig *syslog_config)
 {
     char *tstamp;
-    char user_msg[256];
-    char srcip_msg[256];
-    
-    char syslog_msg[OS_SIZE_2048 +1];
+    char syslog_msg[OS_SIZE_2048];
+
+    /* These will be Malloc'd, so no need to predeclare size, just remember to free! */
+    char *json_safe_comment;
+    char *json_safe_message;
 
+    /* padding value */
+    int padding = 0;
 
     /* Invalid socket. */
     if(syslog_config->socket < 0)
     {
         return(0);
     }
-    
+
 
     /* Clearing the memory before insert */
-    memset(syslog_msg, '\0', OS_SIZE_2048 +1);
+    memset(syslog_msg, '\0', OS_SIZE_2048);
 
 
     /* Looking if location is set */
@@ -101,7 +101,7 @@ int OS_Alert_SendSyslog(alert_data *al_data, SyslogConfig *syslog_config)
     }
 
 
-    /* Fixing the timestamp to be syslog compatible. 
+    /* Fixing the timestamp to be syslog compatible.
      * We have 2008 Jul 10 10:11:23
      * Should be: Jul 10 10:11:23
      */
@@ -110,60 +110,157 @@ int OS_Alert_SendSyslog(alert_data *al_data, SyslogConfig *syslog_config)
     {
         tstamp+=5;
 
-        /* Fixing first digit if the day is < 10 */ 
+        /* Fixing 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';
+
+    /* Remove the double quotes from "dangerous" fields */
+    if( (json_safe_comment = os_strip_char(al_data->comment, '"')) == NULL ) {
+        return(0);
     }
-    else
-    {
-        snprintf(srcip_msg, 255, " srcip: %s;", al_data->srcip);
+    if( (json_safe_message = os_strip_char(al_data->log[0], '"')) == NULL ) {
+        return(0);
     }
 
-
-    /* Adding username. */
-    if(!al_data->user || 
-       ((al_data->user[0] == '(') &&
-        (al_data->user[1] == 'n') &&
-        (al_data->user[2] == 'o')))
+    /* Inserting data */
+    if(syslog_config->format == DEFAULT_CSYSLOG)
     {
-        user_msg[0] = '\0';
+               /* Building syslog message. */
+               snprintf(syslog_msg, OS_SIZE_2048,
+                "<%d>%s %s ossec: Alert Level: %d; Rule: %d - %s; Location: %s;",
+                       syslog_config->priority, tstamp, __shost,
+                al_data->level,
+                al_data->rule, al_data->comment,
+                al_data->location
+        );
+        field_add_string(syslog_msg, OS_SIZE_2048, " srcip: %s;", al_data->srcip );
+#ifdef GEOIP
+        field_add_string(syslog_msg, OS_SIZE_2048, " srccity: %s;", al_data->geoipdatasrc );
+        field_add_string(syslog_msg, OS_SIZE_2048, " dstcity: %s;", al_data->geoipdatadst );
+#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 );
+        field_add_truncated(syslog_msg, OS_SIZE_2048, " %s", al_data->log[0], 2 );
     }
-    else
+    else if(syslog_config->format == CEF_CSYSLOG)
     {
-        snprintf(user_msg, 255, " user: %s;", al_data->user);
+               snprintf(syslog_msg, OS_SIZE_2048,
+
+                "<%d>%s CEF:0|%s|%s|%s|%d|%s|%d|dvc=%s cs2=%s cs2Label=Location",
+                       syslog_config->priority,
+               tstamp,
+               __author,
+               __name,
+               __version,
+               al_data->rule,
+               al_data->comment,
+               (al_data->level > 10) ? 10 : al_data->level,
+                __shost, al_data->location);
+
+        field_add_string(syslog_msg, OS_SIZE_2048, " src=%s", al_data->srcip );
+#ifdef GEOIP
+        field_add_string(syslog_msg, OS_SIZE_2048, " cs3Label=SrcCity cs3=%s", al_data->geoipdatasrc );
+        field_add_string(syslog_msg, OS_SIZE_2048, " cs4Label=DstCity cs4=%s", al_data->geoipdatadst );
+#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, " 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 );
+        }
     }
+    else if(syslog_config->format == JSON_CSYSLOG)
+    {
+        // Padding is two to make sure we can fit closign bracket
+        padding = 2;
+        /* Build a JSON Object for logging */
+        snprintf(syslog_msg, OS_SIZE_2048 - padding,
+                "<%d>%s %s ossec: { \"crit\": %d, \"id\": %d, \"description\": \"%s\", \"component\": \"%s\",",
 
+                /* syslog header */
+                syslog_config->priority, tstamp, __shost,
 
-    /* Inserting data */
-    if(syslog_config->format == DEFAULT_CSYSLOG)
+                /* OSSEC metadata */
+                al_data->level, al_data->rule, json_safe_comment,
+                al_data->location
+        );
+        /* Event specifics */
+        field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"classification\": \"%s\",", al_data->group );
+
+        if( field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"src_ip\": \"%s\",", al_data->srcip ) > 0 )
+            field_add_int(syslog_msg, OS_SIZE_2048 - padding, " \"src_port\": %d,", al_data->srcport );
+
+#ifdef GEOIP
+        field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"src_city\": \"%s\",", al_data->geoipdatasrc );
+        field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"dst_city\": \"%s\",", al_data->geoipdatadst );
+#endif
+
+        if ( field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"dst_ip\": \"%s\",", al_data->dstip ) > 0 )
+            field_add_int(syslog_msg, OS_SIZE_2048 - padding, " \"dst_port\": %d,", al_data->dstport );
+
+        field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"file\": \"%s\",", al_data->filename );
+        field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"acct\": \"%s\",", al_data->user );
+        field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"md5_old\": \"%s\",", al_data->old_md5 );
+        field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"md5_new\": \"%s\",", al_data->new_md5 );
+        field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"sha1_old\": \"%s\",", al_data->old_sha1 );
+        field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"sha1_new\": \"%s\",", al_data->new_sha1 );
+               /* Message */
+        field_add_truncated(syslog_msg, OS_SIZE_2048 - padding, " \"message\": \"%s\"", json_safe_message, 2 );
+        /* Closing brace */
+        field_add_string(syslog_msg, OS_SIZE_2048, " }", "" );
+    }
+    else if(syslog_config->format == SPLUNK_CSYSLOG)
     {
-        /* Building syslog message. */
+        /* Build a Splunk Style Key/Value string for logging */
         snprintf(syslog_msg, OS_SIZE_2048,
-                "<%d>%s %s ossec: Alert Level: %d; Rule: %d - %s; "
-                "Location: %s;%s%s  %s",
+                "<%d>%s %s ossec: crit=%d id=%d description=\"%s\" component=\"%s\",",
+
+                /* syslog header */
                 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]);
+                /* OSSEC metadata */
+                al_data->level, al_data->rule, json_safe_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 GEOIP
+        field_add_string(syslog_msg, OS_SIZE_2048, " src_city=\"%s\",", al_data->geoipdatasrc );
+        field_add_string(syslog_msg, OS_SIZE_2048, " dst_city=\"%s\",", al_data->geoipdatadst );
+#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\"", json_safe_message, 2 );
     }
 
 
     OS_SendUDPbySize(syslog_config->socket, strlen(syslog_msg), syslog_msg);
-    
+    /* Free the malloc'd variables */
+    free(json_safe_comment);
+    free(json_safe_message);
+
     return(1);
 }