Imported Upstream version 2.7
[ossec-hids.git] / src / os_csyslogd / alert.c
1 /* @(#) $Id: ./src/os_csyslogd/alert.c, 2011/09/08 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 Trend Micro Inc.
5  * All rights reserved.
6  *
7  * This program is a free software; you can redistribute it
8  * and/or modify it under the terms of the GNU General Public
9  * License (version 2) as published by the FSF - Free Software
10  * Foundation
11  *
12  * License details at the LICENSE file included with OSSEC or
13  * online at: http://www.ossec.net/en/licensing.html
14  */
15
16
17 #include "csyslogd.h"
18 #include "config/config.h"
19 #include "os_net/os_net.h"
20
21 /** int OS_Alert_SendSyslog
22  * Sends an alert via syslog.
23  * Returns 1 on success or 0 on error.
24  */
25 int OS_Alert_SendSyslog(alert_data *al_data, SyslogConfig *syslog_config)
26 {
27     char *tstamp;
28     char syslog_msg[OS_SIZE_2048];
29
30     /* These will be Malloc'd, so no need to predeclare size, just remember to free! */
31     char *json_safe_comment;
32     char *json_safe_message;
33
34     /* padding value */
35     int padding = 0;
36
37     /* Invalid socket. */
38     if(syslog_config->socket < 0)
39     {
40         return(0);
41     }
42
43
44     /* Clearing the memory before insert */
45     memset(syslog_msg, '\0', OS_SIZE_2048);
46
47
48     /* Looking if location is set */
49     if(syslog_config->location)
50     {
51         if(!OSMatch_Execute(al_data->location,
52                             strlen(al_data->location),
53                             syslog_config->location))
54         {
55             return(0);
56         }
57     }
58
59
60     /* Looking for the level */
61     if(syslog_config->level)
62     {
63         if(al_data->level < syslog_config->level)
64         {
65             return(0);
66         }
67     }
68
69
70     /* Looking for rule id */
71     if(syslog_config->rule_id)
72     {
73         int id_i = 0;
74         while(syslog_config->rule_id[id_i] != 0)
75         {
76             if(syslog_config->rule_id[id_i] == al_data->rule)
77             {
78                 break;
79             }
80             id_i++;
81         }
82
83
84         /* If we found, id is going to be a valid rule */
85         if(!syslog_config->rule_id[id_i])
86         {
87             return(0);
88         }
89     }
90
91
92     /* Looking for the group */
93     if(syslog_config->group)
94     {
95         if(!OSMatch_Execute(al_data->group,
96                             strlen(al_data->group),
97                             syslog_config->group))
98         {
99             return(0);
100         }
101     }
102
103
104     /* Fixing the timestamp to be syslog compatible.
105      * We have 2008 Jul 10 10:11:23
106      * Should be: Jul 10 10:11:23
107      */
108     tstamp = al_data->date;
109     if(strlen(al_data->date) > 14)
110     {
111         tstamp+=5;
112
113         /* Fixing first digit if the day is < 10 */
114         if(tstamp[4] == '0')
115             tstamp[4] = ' ';
116     }
117
118
119     /* Remove the double quotes from "dangerous" fields */
120     if( (json_safe_comment = os_strip_char(al_data->comment, '"')) == NULL ) {
121         return(0);
122     }
123     if( (json_safe_message = os_strip_char(al_data->log[0], '"')) == NULL ) {
124         return(0);
125     }
126
127     /* Inserting data */
128     if(syslog_config->format == DEFAULT_CSYSLOG)
129     {
130         /* Building syslog message. */
131         snprintf(syslog_msg, OS_SIZE_2048,
132                 "<%d>%s %s ossec: Alert Level: %d; Rule: %d - %s; Location: %s;",
133                 syslog_config->priority, tstamp, __shost,
134                 al_data->level,
135                 al_data->rule, al_data->comment,
136                 al_data->location
137         );
138         field_add_string(syslog_msg, OS_SIZE_2048, " srcip: %s;", al_data->srcip );
139 #ifdef GEOIP
140         field_add_string(syslog_msg, OS_SIZE_2048, " srccity: %s;", al_data->geoipdatasrc );
141         field_add_string(syslog_msg, OS_SIZE_2048, " dstcity: %s;", al_data->geoipdatadst );
142 #endif
143         field_add_string(syslog_msg, OS_SIZE_2048, " dstip: %s;", al_data->dstip );
144         field_add_string(syslog_msg, OS_SIZE_2048, " user: %s;", al_data->user );
145         field_add_string(syslog_msg, OS_SIZE_2048, " Previous MD5: %s;", al_data->old_md5 );
146         field_add_string(syslog_msg, OS_SIZE_2048, " Current MD5: %s;", al_data->new_md5 );
147         field_add_string(syslog_msg, OS_SIZE_2048, " Previous SHA1: %s;", al_data->old_sha1 );
148         field_add_string(syslog_msg, OS_SIZE_2048, " Current SHA1: %s;", al_data->new_sha1 );
149         field_add_truncated(syslog_msg, OS_SIZE_2048, " %s", al_data->log[0], 2 );
150     }
151     else if(syslog_config->format == CEF_CSYSLOG)
152     {
153         snprintf(syslog_msg, OS_SIZE_2048,
154
155                 "<%d>%s CEF:0|%s|%s|%s|%d|%s|%d|dvc=%s cs2=%s cs2Label=Location",
156                 syslog_config->priority,
157                 tstamp,
158                 __author,
159                 __name,
160                 __version,
161                 al_data->rule,
162                 al_data->comment,
163                 (al_data->level > 10) ? 10 : al_data->level,
164                 __shost, al_data->location);
165
166         field_add_string(syslog_msg, OS_SIZE_2048, " src=%s", al_data->srcip );
167 #ifdef GEOIP
168         field_add_string(syslog_msg, OS_SIZE_2048, " cs3Label=SrcCity cs3=%s", al_data->geoipdatasrc );
169         field_add_string(syslog_msg, OS_SIZE_2048, " cs4Label=DstCity cs4=%s", al_data->geoipdatadst );
170 #endif
171         field_add_string(syslog_msg, OS_SIZE_2048, " suser=%s", al_data->user );
172         field_add_string(syslog_msg, OS_SIZE_2048, " dst=%s", al_data->dstip );
173         field_add_truncated(syslog_msg, OS_SIZE_2048, " msg=%s", al_data->log[0], 2 );
174         if (al_data->new_md5 && al_data->new_sha1) {
175             field_add_string(syslog_msg, OS_SIZE_2048, " Previous MD5: %s", al_data->old_md5 );
176             field_add_string(syslog_msg, OS_SIZE_2048, " Current MD5: %s", al_data->new_md5 );
177             field_add_string(syslog_msg, OS_SIZE_2048, " Previous SHA1: %s", al_data->old_sha1 );
178             field_add_string(syslog_msg, OS_SIZE_2048, " Current SHA1: %s", al_data->new_sha1 );
179         }
180     }
181     else if(syslog_config->format == JSON_CSYSLOG)
182     {
183         // Padding is two to make sure we can fit closign bracket
184         padding = 2;
185         /* Build a JSON Object for logging */
186         snprintf(syslog_msg, OS_SIZE_2048 - padding,
187                 "<%d>%s %s ossec: { \"crit\": %d, \"id\": %d, \"description\": \"%s\", \"component\": \"%s\",",
188
189                 /* syslog header */
190                 syslog_config->priority, tstamp, __shost,
191
192                 /* OSSEC metadata */
193                 al_data->level, al_data->rule, json_safe_comment,
194                 al_data->location
195         );
196         /* Event specifics */
197         field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"classification\": \"%s\",", al_data->group );
198
199         if( field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"src_ip\": \"%s\",", al_data->srcip ) > 0 )
200             field_add_int(syslog_msg, OS_SIZE_2048 - padding, " \"src_port\": %d,", al_data->srcport );
201
202 #ifdef GEOIP
203         field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"src_city\": \"%s\",", al_data->geoipdatasrc );
204         field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"dst_city\": \"%s\",", al_data->geoipdatadst );
205 #endif
206
207         if ( field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"dst_ip\": \"%s\",", al_data->dstip ) > 0 )
208             field_add_int(syslog_msg, OS_SIZE_2048 - padding, " \"dst_port\": %d,", al_data->dstport );
209
210         field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"file\": \"%s\",", al_data->filename );
211         field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"acct\": \"%s\",", al_data->user );
212         field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"md5_old\": \"%s\",", al_data->old_md5 );
213         field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"md5_new\": \"%s\",", al_data->new_md5 );
214         field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"sha1_old\": \"%s\",", al_data->old_sha1 );
215         field_add_string(syslog_msg, OS_SIZE_2048 - padding, " \"sha1_new\": \"%s\",", al_data->new_sha1 );
216                 /* Message */
217         field_add_truncated(syslog_msg, OS_SIZE_2048 - padding, " \"message\": \"%s\"", json_safe_message, 2 );
218         /* Closing brace */
219         field_add_string(syslog_msg, OS_SIZE_2048, " }", "" );
220     }
221     else if(syslog_config->format == SPLUNK_CSYSLOG)
222     {
223         /* Build a Splunk Style Key/Value string for logging */
224         snprintf(syslog_msg, OS_SIZE_2048,
225                 "<%d>%s %s ossec: crit=%d id=%d description=\"%s\" component=\"%s\",",
226
227                 /* syslog header */
228                 syslog_config->priority, tstamp, __shost,
229
230                 /* OSSEC metadata */
231                 al_data->level, al_data->rule, json_safe_comment,
232                 al_data->location
233         );
234         /* Event specifics */
235         field_add_string(syslog_msg, OS_SIZE_2048, " classification=\"%s\",", al_data->group );
236
237         if( field_add_string(syslog_msg, OS_SIZE_2048, " src_ip=\"%s\",", al_data->srcip ) > 0 )
238             field_add_int(syslog_msg, OS_SIZE_2048, " src_port=%d,", al_data->srcport );
239
240 #ifdef GEOIP
241         field_add_string(syslog_msg, OS_SIZE_2048, " src_city=\"%s\",", al_data->geoipdatasrc );
242         field_add_string(syslog_msg, OS_SIZE_2048, " dst_city=\"%s\",", al_data->geoipdatadst );
243 #endif
244
245         if( field_add_string(syslog_msg, OS_SIZE_2048, " dst_ip=\"%s\",", al_data->dstip ) > 0 )
246             field_add_int(syslog_msg, OS_SIZE_2048, " dst_port=%d,", al_data->dstport );
247
248         field_add_string(syslog_msg, OS_SIZE_2048, " file=\"%s\",", al_data->filename );
249         field_add_string(syslog_msg, OS_SIZE_2048, " acct=\"%s\",", al_data->user );
250         field_add_string(syslog_msg, OS_SIZE_2048, " md5_old=\"%s\",", al_data->old_md5 );
251         field_add_string(syslog_msg, OS_SIZE_2048, " md5_new=\"%s\",", al_data->new_md5 );
252         field_add_string(syslog_msg, OS_SIZE_2048, " sha1_old=\"%s\",", al_data->old_sha1 );
253         field_add_string(syslog_msg, OS_SIZE_2048, " sha1_new=\"%s\",", al_data->new_sha1 );
254         /* Message */
255         field_add_truncated(syslog_msg, OS_SIZE_2048, " message=\"%s\"", json_safe_message, 2 );
256     }
257
258
259     OS_SendUDPbySize(syslog_config->socket, strlen(syslog_msg), syslog_msg);
260     /* Free the malloc'd variables */
261     free(json_safe_comment);
262     free(json_safe_message);
263
264     return(1);
265 }
266
267
268 /* EOF */