new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / os_dbd / 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 "dbd.h"
11 #include "config/config.h"
12 #include "config/dbd-config.h"
13 #include "rules_op.h"
14
15 /* Prototypes */
16 static int __DBSelectLocation(const char *location, const DBConfig *db_config) __attribute__((nonnull));
17 static int __DBInsertLocation(const char *location, const DBConfig *db_config) __attribute__((nonnull));
18
19
20 /* Select the maximum ID from the alert table
21  * Returns 0 if not found
22  */
23 int OS_SelectMaxID(const DBConfig *db_config)
24 {
25     int result = 0;
26     char sql_query[OS_SIZE_1024];
27
28     memset(sql_query, '\0', OS_SIZE_1024);
29
30     /* Generate SQL */
31     snprintf(sql_query, OS_SIZE_1024 - 1,
32              "SELECT MAX(id) FROM "
33              "alert WHERE server_id = '%u'",
34              db_config->server_id);
35
36     result = osdb_query_select(db_config->conn, sql_query);
37
38     return (result);
39 }
40
41
42 /* Select the location ID from the db
43  * Returns 0 if not found
44  */
45 static int __DBSelectLocation(const char *location, const DBConfig *db_config)
46 {
47     int result = 0;
48     char sql_query[OS_SIZE_1024];
49
50     memset(sql_query, '\0', OS_SIZE_1024);
51
52     /* Generate SQL */
53     snprintf(sql_query, OS_SIZE_1024 - 1,
54              "SELECT id FROM "
55              "location WHERE name = '%s' AND server_id = '%d' "
56              "LIMIT 1",
57              location, db_config->server_id);
58
59     result = osdb_query_select(db_config->conn, sql_query);
60
61     return (result);
62 }
63
64 /* Insert location in to the db */
65 static int __DBInsertLocation(const char *location, const DBConfig *db_config)
66 {
67     char sql_query[OS_SIZE_1024];
68
69     memset(sql_query, '\0', OS_SIZE_1024);
70
71     /* Generate SQL */
72     snprintf(sql_query, OS_SIZE_1024 - 1,
73              "INSERT INTO "
74              "location(server_id, name) "
75              "VALUES ('%u', '%s')",
76              db_config->server_id, location);
77
78     if (!osdb_query_insert(db_config->conn, sql_query)) {
79         merror(DB_GENERROR, ARGV0);
80     }
81
82     return (0);
83 }
84
85 /* Insert alert into to the db
86  * Returns 1 on success or 0 on error
87  */
88 int OS_Alert_InsertDB(const alert_data *al_data, DBConfig *db_config)
89 {
90     int i;
91     unsigned int location_id = 0;
92     unsigned short s_port = 0, d_port = 0;
93     int *loc_id;
94     char sql_query[OS_SIZE_8192 + 1];
95     char *fulllog = NULL;
96
97     /* Clear the memory before insert */
98     sql_query[0] = '\0';
99     sql_query[OS_SIZE_8192] = '\0';
100
101     /* Source Port */
102     s_port = al_data->srcport;
103
104     /* Destination Port */
105     d_port = al_data->dstport;
106
107     /* Escape strings */
108     osdb_escapestr(al_data->user);
109     osdb_escapestr(al_data->location);
110     
111     /* We first need to insert the location */
112     loc_id = (int *) OSHash_Get(db_config->location_hash, al_data->location);
113
114     /* If we dont have location id, we must select and/or insert in the db */
115     if (!loc_id) {
116         location_id = __DBSelectLocation(al_data->location, db_config);
117         if (location_id == 0) {
118             /* Insert it */
119             __DBInsertLocation(al_data->location, db_config);
120             location_id = __DBSelectLocation(al_data->location, db_config);
121         }
122
123         if (!location_id) {
124             merror("%s: Unable to insert location: '%s'.",
125                    ARGV0, al_data->location);
126             return (0);
127         }
128
129         /* Add to hash */
130         os_calloc(1, sizeof(int), loc_id);
131         *loc_id = location_id;
132         OSHash_Add(db_config->location_hash, al_data->location, loc_id);
133     }
134
135     i = 0;
136     while (al_data->log[i]) {
137         size_t len = strlen(al_data->log[i]);
138         char templog[len + 2];
139         if (al_data->log[i + 1]) {
140             snprintf(templog, len + 2, "%s\n", al_data->log[i]);
141         } else {
142             snprintf(templog, len + 1, "%s", al_data->log[i]);
143         }
144         fulllog = os_LoadString(fulllog, templog);
145         i++;
146     }
147
148     if (fulllog == NULL) {
149         merror("%s: Unable to process log.", ARGV0);
150         return (0);
151     }
152
153     osdb_escapestr(fulllog);
154     if (strlen(fulllog) >  7456) {
155         fulllog[7454] = '.';
156         fulllog[7455] = '.';
157         fulllog[7456] = '\0';
158     }
159
160     /* Generate final SQL */
161     switch (db_config->db_type) {
162       case MYSQLDB:
163         snprintf(sql_query, OS_SIZE_8192,
164                  "INSERT INTO "
165                  "alert(server_id,rule_id,level,timestamp,location_id,src_ip,src_port,dst_ip,dst_port,alertid,user,full_log,tld) "
166                  "VALUES ('%u', '%u','%u','%u', '%u', '%s', '%u', '%s', '%u', '%s', '%s', '%s','%.2s')",
167                  db_config->server_id, al_data->rule,
168                  al_data->level,
169                  (unsigned int)time(0), *loc_id,
170                  al_data->srcip,
171                  (unsigned short)s_port,
172                  al_data->dstip,
173                  (unsigned short)d_port,
174                  al_data->alertid,
175                  al_data->user, fulllog, al_data->srcgeoip);
176         break;
177
178       case POSTGDB:
179         snprintf(sql_query, OS_SIZE_8192,
180                  "INSERT INTO "
181                  "alert(server_id,rule_id,level,timestamp,location_id,src_ip,src_port,dst_ip,dst_port,alertid,\"user\",full_log) "
182                  "VALUES ('%u', '%u','%u','%u', '%u', '%s', '%u', '%s', '%u', '%s', '%s', '%s')",
183                  db_config->server_id, al_data->rule,
184                  al_data->level,
185                  (unsigned int)time(0), *loc_id,
186                  al_data->srcip != NULL ? al_data->srcip : "NULL",
187                  (unsigned short)s_port,
188                  al_data->dstip != NULL ? al_data->dstip : "NULL",
189                  (unsigned short)d_port,
190                  al_data->alertid,
191                  al_data->user != NULL ? al_data->user : "NULL",
192                  fulllog);
193         break;
194     }
195
196     free(fulllog);
197     fulllog = NULL;
198
199     /* Insert into the db */
200     if (!osdb_query_insert(db_config->conn, sql_query)) {
201         merror(DB_GENERROR, ARGV0);
202     }
203
204     db_config->alert_id++;
205     return (1);
206 }