deba5ea6d424a7f7e1b19d348c1a10226df1187a
[ossec-hids.git] / db_op.c
1 /* @(#) $Id: ./src/os_dbd/db_op.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 /* Common lib for dealing with databases */
18
19
20 #include "dbd.h"
21
22 /* Using Mysql */
23 #ifdef UMYSQL
24 #include <mysql.h>
25 #endif
26
27 /* Using PostgreSQL */
28 #ifdef UPOSTGRES
29 #include <libpq-fe.h>
30 #endif
31
32
33
34 /* Config pointer */
35 DBConfig *db_config_pt = NULL;
36
37
38
39 /** void osdb_escapestr
40  * Escapes a null terminated string before inserting into the database.
41  * We built a white list of allowed characters at insert_map. Everything
42  * not allowed will become spaces.
43  */
44 void osdb_escapestr(char *str)
45 {
46     if(!str)
47     {
48         return;
49     }
50
51     while(*str)
52     {
53         if(*str == '\'')
54         {
55             *str = '`';
56         }
57         else if(*str == '\\')
58         {
59             *str = '/';
60         }
61         else if(insert_map[(unsigned char)*str] != '\001')
62         {
63             *str = ' ';
64         }
65         str++;
66     }
67
68     /* It can not end with \\ */
69     if(*(str -1) == '\\')
70     {
71         *(str-1) = '\0';
72     }
73 }
74
75
76
77 /** void osdb_checkerror()
78  * Checks for errors and handle it appropriately.
79  */
80 void osdb_checkerror()
81 {
82     int sleep_time = 2;
83     if(!db_config_pt || db_config_pt->error_count > 20)
84     {
85         ErrorExit(DB_MAINERROR, ARGV0);
86     }
87
88
89     /* If error count is too large, we try to reconnect. */
90     if(db_config_pt->error_count > 0)
91     {
92         int i = 0;
93         if(db_config_pt->conn)
94         {
95             osdb_close(db_config_pt->conn);
96             db_config_pt->conn = NULL;
97         }
98
99         while(i <= db_config_pt->maxreconnect)
100         {
101             merror(DB_ATTEMPT, ARGV0);
102             db_config_pt->conn = osdb_connect(db_config_pt->host,
103                                               db_config_pt->user,
104                                               db_config_pt->pass,
105                                               db_config_pt->db,
106                                               db_config_pt->port,
107                                               db_config_pt->sock);
108
109             /* If we were able to reconnect, keep going. */
110             if(db_config_pt->conn)
111             {
112                 break;
113             }
114             sleep(sleep_time);
115             sleep_time *= 2;
116             i++;
117         }
118
119
120         /* If we weren't able to connect, exit */
121         if(!db_config_pt->conn)
122         {
123             ErrorExit(DB_MAINERROR, ARGV0);
124         }
125
126
127         verbose("%s: Connected to database '%s' at '%s'.",
128                 ARGV0, db_config_pt->db, db_config_pt->host);
129
130     }
131 }
132
133
134 /** void osdb_seterror()
135  * Sets the error counter.
136  */
137 void osdb_seterror()
138 {
139     db_config_pt->error_count++;
140     osdb_checkerror();
141 }
142
143
144 /** void osdb_setconfig(DBConfig *db_config)
145  * Creates an internal pointer to the db configuration.
146  */
147 void osdb_setconfig(DBConfig *db_config)
148 {
149     db_config_pt = db_config;
150 }
151
152
153
154 /** MySQL calls **/
155 #ifdef UMYSQL
156
157
158 /* Create the database connection.
159  * Returns NULL on error
160  */
161 void *mysql_osdb_connect(char *host, char *user, char *pass, char *db,
162                          int port, char *sock)
163 {
164     MYSQL *conn;
165     conn = mysql_init(NULL);
166     if (conn == NULL)
167     {
168         merror(DBINIT_ERROR, ARGV0);
169         return(NULL);
170     }
171
172
173     /* If host is 127.0.0.1 or localhost, use tcp socket */
174     if((strcmp(host, "127.0.0.1") == 0) ||
175        (strcmp(host, "localhost") == 0))
176     {
177         if(sock != NULL)
178         {
179             mysql_options(conn, MYSQL_OPT_NAMED_PIPE, NULL);
180         }
181         else
182         {
183             unsigned int p_type = MYSQL_PROTOCOL_TCP;
184             mysql_options(conn, MYSQL_OPT_PROTOCOL, (char *)&p_type);
185         }
186     }
187     if(mysql_real_connect(conn, host, user, pass, db,
188                           port, sock, 0) == NULL)
189     {
190         merror(DBCONN_ERROR, ARGV0, host, db, mysql_error(conn));
191         mysql_close(conn);
192         return(NULL);
193     }
194
195     return(conn);
196 }
197
198
199
200 /* Closes the database connection.
201  */
202 void *mysql_osdb_close(void *db_conn)
203 {
204     merror(DB_CLOSING, ARGV0);
205     mysql_close(db_conn);
206     return(NULL);
207 }
208
209
210
211 /** int mysql_osdb_query_insert(void *db_conn, char *query)
212  * Sends insert query to database.
213  */
214 int mysql_osdb_query_insert(void *db_conn, char *query)
215 {
216     if(mysql_query(db_conn, query) != 0)
217     {
218         /* failure; report error */
219         merror(DBQUERY_ERROR, ARGV0, query, mysql_error(db_conn));
220         osdb_seterror();
221         return(0);
222     }
223
224     return(1);
225 }
226
227
228
229 /** int mysql_osdb_query_select(void *db_conn, char *query)
230  * Sends a select query to database. Returns the value of it.
231  * Returns 0 on error (not found).
232  */
233 int mysql_osdb_query_select(void *db_conn, char *query)
234 {
235     int result_int = 0;
236     MYSQL_RES *result_data;
237     MYSQL_ROW result_row;
238
239
240     /* Sending the query. It can not fail. */
241     if(mysql_query(db_conn, query) != 0)
242     {
243         /* failure; report error */
244         merror(DBQUERY_ERROR, ARGV0, query, mysql_error(db_conn));
245         osdb_seterror();
246         return(0);
247     }
248
249
250     /* Getting result */
251     result_data = mysql_use_result(db_conn);
252     if(result_data == NULL)
253     {
254         /* failure; report error */
255         merror(DBQUERY_ERROR, ARGV0, query, mysql_error(db_conn));
256         osdb_seterror();
257         return(0);
258     }
259
260
261     /* Getting row. We only care about the first result. */
262     result_row = mysql_fetch_row(result_data);
263     if(result_row && (result_row[0] != NULL))
264     {
265         result_int = atoi(result_row[0]);
266     }
267
268
269     mysql_free_result(result_data);
270
271
272     return(result_int);
273 }
274 #endif
275 /** End of MYSQL calls **/
276
277
278
279
280 /** PostGRES Calls **/
281 #if defined UPOSTGRES
282
283
284 /** void *postgresql_osdb_connect(char *host, char *user, char *pass, char *db)
285  * Create the PostgreSQL database connection.
286  * Return NULL on error
287  */
288 void *postgresql_osdb_connect(char *host, char *user, char *pass, char *db,
289                               int port, char *sock)
290 {
291     PGconn *conn;
292
293
294     conn = PQsetdbLogin(host, NULL, NULL, NULL, db, user, pass);
295     if(PQstatus(conn) == CONNECTION_BAD)
296     {
297         merror(DBCONN_ERROR, ARGV0, host, db, PQerrorMessage(conn));
298         PQfinish(conn);
299         return(NULL);
300     }
301
302     return(conn);
303 }
304
305
306
307 /** void postgresql_osdb_close(void *db_conn)
308  * Terminates db connection.
309  */
310 void *postgresql_osdb_close(void *db_conn)
311 {
312     merror(DB_CLOSING, ARGV0);
313     PQfinish(db_conn);
314     return(NULL);
315 }
316
317
318
319 /** int postgresql_osdb_query_insert(void *db_conn, char *query)
320  * Sends insert query to database.
321  */
322 int postgresql_osdb_query_insert(void *db_conn, char *query)
323 {
324     PGresult *result;
325
326
327     result = PQexec(db_conn,query);
328     if(!result)
329     {
330         merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn));
331         osdb_seterror();
332         return(0);
333     }
334
335
336     if(PQresultStatus(result) != PGRES_COMMAND_OK)
337     {
338         merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn));
339         PQclear(result);
340         osdb_seterror();
341         return(0);
342     }
343
344
345     PQclear(result);
346     return(1);
347 }
348
349
350
351 /** int postgresql_osdb_query_select(void *db_conn, char *query)
352  * Sends a select query to database. Returns the value of it.
353  * Returns 0 on error (not found).
354  */
355 int postgresql_osdb_query_select(void *db_conn, char *query)
356 {
357     int result_int = 0;
358     PGresult *result;
359
360     result = PQexec(db_conn,query);
361     if(!result)
362     {
363         merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn));
364         osdb_seterror();
365         return(0);
366     }
367
368     if((PQresultStatus(result) == PGRES_TUPLES_OK))
369     {
370         if(PQntuples(result) == 1)
371         {
372             result_int = atoi(PQgetvalue(result,0,0));
373         }
374     }
375     else
376     {
377         merror(DBQUERY_ERROR, ARGV0, query, PQerrorMessage(db_conn));
378         osdb_seterror();
379         return(0);
380     }
381
382
383     /* Clear result */
384     PQclear(result);
385
386
387     return(result_int);
388 }
389 /** End of PostGRES calls **/
390 #endif
391
392
393
394 /* Everything else when db is not defined. */
395 #if !defined(UPOSTGRES) && !defined(UMYSQL)
396
397
398
399 void *none_osdb_connect(char *host, char *user, char *pass, char *db,
400                         int port, char *sock)
401 {
402     merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0);
403     return(NULL);
404 }
405 void *none_osdb_close(void *db_conn)
406 {
407     merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0);
408     return(NULL);
409 }
410 void *none_osdb_query_insert(void *db_conn, char *query)
411 {
412    merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0);
413     return(0);
414 }
415 void *none_osdb_query_select(void *db_conn, char *query)
416 {
417     merror("%s: ERROR: Database support not enabled. Exiting.", ARGV0);
418     return(0);
419 }
420
421
422
423
424 /** End of not defined db calls **/
425 #endif
426
427
428
429 /* EOF */