bf7572f1a89f8dfd05470c3b3845a76ce2fd26d4
[ossec-hids.git] / 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 "cJSON.h"
19 #include "config/config.h"
20 #include "os_net/os_net.h"
21
22 /** int OS_Alert_SendSyslog
23  * Sends an alert via syslog.
24  * Returns 1 on success or 0 on error.
25  */
26 int OS_Alert_SendSyslog(alert_data *al_data, SyslogConfig *syslog_config)
27 {
28     char *tstamp;
29     char syslog_msg[OS_SIZE_2048];
30
31     /* padding value */
32     int padding = 0;
33
34     /* Invalid socket. */
35     if(syslog_config->socket < 0)
36     {
37         return(0);
38     }
39
40
41     /* Clearing the memory before insert */
42     memset(syslog_msg, '\0', OS_SIZE_2048);
43
44
45     /* Looking if location is set */
46     if(syslog_config->location)
47     {
48         if(!OSMatch_Execute(al_data->location,
49                             strlen(al_data->location),
50                             syslog_config->location))
51         {
52             return(0);
53         }
54     }
55
56
57     /* Looking for the level */
58     if(syslog_config->level)
59     {
60         if(al_data->level < syslog_config->level)
61         {
62             return(0);
63         }
64     }
65
66
67     /* Looking for rule id */
68     if(syslog_config->rule_id)
69     {
70         int id_i = 0;
71         while(syslog_config->rule_id[id_i] != 0)
72         {
73             if(syslog_config->rule_id[id_i] == al_data->rule)
74             {
75                 break;
76             }
77             id_i++;
78         }
79
80
81         /* If we found, id is going to be a valid rule */
82         if(!syslog_config->rule_id[id_i])
83         {
84             return(0);
85         }
86     }
87
88
89     /* Looking for the group */
90     if(syslog_config->group)
91     {
92         if(!OSMatch_Execute(al_data->group,
93                             strlen(al_data->group),
94                             syslog_config->group))
95         {
96             return(0);
97         }
98     }
99
100
101     /* Fixing the timestamp to be syslog compatible.
102      * We have 2008 Jul 10 10:11:23
103      * Should be: Jul 10 10:11:23
104      */
105     tstamp = al_data->date;
106     if(strlen(al_data->date) > 14)
107     {
108         tstamp+=5;
109
110         /* Fixing first digit if the day is < 10 */
111         if(tstamp[4] == '0')
112             tstamp[4] = ' ';
113     }
114
115     /* Inserting data */
116     if(syslog_config->format == DEFAULT_CSYSLOG)
117     {
118         /* Building syslog message. */
119         snprintf(syslog_msg, OS_SIZE_2048,
120                 "<%d>%s %s ossec: Alert Level: %d; Rule: %d - %s; Location: %s;",
121                 syslog_config->priority, tstamp, __shost,
122                 al_data->level,
123                 al_data->rule, al_data->comment,
124                 al_data->location
125         );
126         field_add_string(syslog_msg, OS_SIZE_2048, " srcip: %s;", al_data->srcip );
127 #ifdef GEOIP
128         field_add_string(syslog_msg, OS_SIZE_2048, " srccity: %s;", al_data->geoipdatasrc );
129         field_add_string(syslog_msg, OS_SIZE_2048, " dstcity: %s;", al_data->geoipdatadst );
130 #endif
131         field_add_string(syslog_msg, OS_SIZE_2048, " dstip: %s;", al_data->dstip );
132         field_add_string(syslog_msg, OS_SIZE_2048, " user: %s;", al_data->user );
133         field_add_string(syslog_msg, OS_SIZE_2048, " Previous MD5: %s;", al_data->old_md5 );
134         field_add_string(syslog_msg, OS_SIZE_2048, " Current MD5: %s;", al_data->new_md5 );
135         field_add_string(syslog_msg, OS_SIZE_2048, " Previous SHA1: %s;", al_data->old_sha1 );
136         field_add_string(syslog_msg, OS_SIZE_2048, " Current SHA1: %s;", al_data->new_sha1 );
137         field_add_truncated(syslog_msg, OS_SIZE_2048, " %s", al_data->log[0], 2 );
138     }
139     else if(syslog_config->format == CEF_CSYSLOG)
140     {
141         snprintf(syslog_msg, OS_SIZE_2048,
142
143                 "<%d>%s CEF:0|%s|%s|%s|%d|%s|%d|dvc=%s cs2=%s cs2Label=Location",
144                 syslog_config->priority,
145                 tstamp,
146                 __author,
147                 __ossec_name,
148                 __version,
149                 al_data->rule,
150                 al_data->comment,
151                 (al_data->level > 10) ? 10 : al_data->level,
152                 __shost, al_data->location);
153
154         field_add_string(syslog_msg, OS_SIZE_2048, " src=%s", al_data->srcip );
155 #ifdef GEOIP
156         field_add_string(syslog_msg, OS_SIZE_2048, " cs3Label=SrcCity cs3=%s", al_data->geoipdatasrc );
157         field_add_string(syslog_msg, OS_SIZE_2048, " cs4Label=DstCity cs4=%s", al_data->geoipdatadst );
158 #endif
159         field_add_string(syslog_msg, OS_SIZE_2048, " suser=%s", al_data->user );
160         field_add_string(syslog_msg, OS_SIZE_2048, " dst=%s", al_data->dstip );
161         field_add_truncated(syslog_msg, OS_SIZE_2048, " msg=%s", al_data->log[0], 2 );
162         if (al_data->new_md5 && al_data->new_sha1) {
163             field_add_string(syslog_msg, OS_SIZE_2048, " Previous MD5: %s", al_data->old_md5 );
164             field_add_string(syslog_msg, OS_SIZE_2048, " Current MD5: %s", al_data->new_md5 );
165             field_add_string(syslog_msg, OS_SIZE_2048, " Previous SHA1: %s", al_data->old_sha1 );
166             field_add_string(syslog_msg, OS_SIZE_2048, " Current SHA1: %s", al_data->new_sha1 );
167         }
168     }
169     else if(syslog_config->format == JSON_CSYSLOG)
170     {
171         /* Build a JSON Object for logging */
172         cJSON *root;
173         char *json_string;
174         root = cJSON_CreateObject();
175
176         // Data guaranteed to be there
177         cJSON_AddNumberToObject(root, "crit",      al_data->level);
178         cJSON_AddNumberToObject(root, "id",        al_data->rule);
179         cJSON_AddStringToObject(root, "component", al_data->location);
180
181         // Rule Meta Data
182         if (al_data->group)   cJSON_AddStringToObject(root, "classification", al_data->group);
183         if (al_data->comment) cJSON_AddStringToObject(root, "description",    al_data->comment);
184
185         // Raw log message generating event
186         if (al_data->log && al_data->log[0])
187                 cJSON_AddStringToObject(root, "message",        al_data->log[0]);
188
189         // Add data if it exists
190         if (al_data->user)       cJSON_AddStringToObject(root,   "acct",       al_data->user);
191         if (al_data->srcip)      cJSON_AddStringToObject(root,   "src_ip",     al_data->srcip);
192         if (al_data->srcport)    cJSON_AddNumberToObject(root,   "src_port",   al_data->srcport);
193         if (al_data->dstip)      cJSON_AddStringToObject(root,   "dst_ip",     al_data->dstip);
194         if (al_data->dstport)    cJSON_AddNumberToObject(root,   "dst_port",   al_data->dstport);
195         if (al_data->filename)   cJSON_AddStringToObject(root,   "file",       al_data->filename);
196         if (al_data->old_md5)    cJSON_AddStringToObject(root,   "md5_old",    al_data->old_md5);
197         if (al_data->new_md5)    cJSON_AddStringToObject(root,   "md5_new",    al_data->new_md5);
198         if (al_data->old_sha1)   cJSON_AddStringToObject(root,   "sha1_old",   al_data->old_sha1);
199         if (al_data->new_sha1)   cJSON_AddStringToObject(root,   "sha1_new",   al_data->new_sha1);
200 #ifdef GEOIP
201         if (al_data->geoipdatasrc) cJSON_AddStringToObject(root, "src_city", al_data->geoipdatasrc);
202         if (al_data->geoipdatadst) cJSON_AddStringToObject(root, "dst_city", al_data->geoipdatadst);
203 #endif
204
205         // Create the JSON String
206         json_string = cJSON_PrintUnformatted(root);
207
208         // Create the syslog message
209         snprintf(syslog_msg, OS_SIZE_2048 - padding,
210                 "<%d>%s %s ossec: %s",
211
212                 /* syslog header */
213                 syslog_config->priority, tstamp, __shost,
214
215                 /* JSON Encoded Data */
216                 json_string
217         );
218         // Cleanup the memory for the JSON Structure
219         free(json_string);
220         cJSON_Delete(root);
221     }
222     else if(syslog_config->format == SPLUNK_CSYSLOG)
223     {
224         /* Build a Splunk Style Key/Value string for logging */
225         snprintf(syslog_msg, OS_SIZE_2048,
226                 "<%d>%s %s ossec: crit=%d id=%d description=\"%s\" component=\"%s\",",
227
228                 /* syslog header */
229                 syslog_config->priority, tstamp, __shost,
230
231                 /* OSSEC metadata */
232                 al_data->level, al_data->rule, al_data->comment,
233                 al_data->location
234         );
235         /* Event specifics */
236         field_add_string(syslog_msg, OS_SIZE_2048, " classification=\"%s\",", al_data->group );
237
238         if( field_add_string(syslog_msg, OS_SIZE_2048, " src_ip=\"%s\",", al_data->srcip ) > 0 )
239             field_add_int(syslog_msg, OS_SIZE_2048, " src_port=%d,", al_data->srcport );
240
241 #ifdef GEOIP
242         field_add_string(syslog_msg, OS_SIZE_2048, " src_city=\"%s\",", al_data->geoipdatasrc );
243         field_add_string(syslog_msg, OS_SIZE_2048, " dst_city=\"%s\",", al_data->geoipdatadst );
244 #endif
245
246         if( field_add_string(syslog_msg, OS_SIZE_2048, " dst_ip=\"%s\",", al_data->dstip ) > 0 )
247             field_add_int(syslog_msg, OS_SIZE_2048, " dst_port=%d,", al_data->dstport );
248
249         field_add_string(syslog_msg, OS_SIZE_2048, " file=\"%s\",", al_data->filename );
250         field_add_string(syslog_msg, OS_SIZE_2048, " acct=\"%s\",", al_data->user );
251         field_add_string(syslog_msg, OS_SIZE_2048, " md5_old=\"%s\",", al_data->old_md5 );
252         field_add_string(syslog_msg, OS_SIZE_2048, " md5_new=\"%s\",", al_data->new_md5 );
253         field_add_string(syslog_msg, OS_SIZE_2048, " sha1_old=\"%s\",", al_data->old_sha1 );
254         field_add_string(syslog_msg, OS_SIZE_2048, " sha1_new=\"%s\",", al_data->new_sha1 );
255         /* Message */
256         field_add_truncated(syslog_msg, OS_SIZE_2048, " message=\"%s\"", al_data->log[0], 2 );
257     }
258
259
260     OS_SendUDPbySize(syslog_config->socket, strlen(syslog_msg), syslog_msg);
261     return(1);
262 }
263
264
265 /* EOF */