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