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