source: trunk/src/sh_database.c@ 402

Last change on this file since 402 was 362, checked in by katerina, 13 years ago

Fix for ticket #267 (Multiple compiler warnings with gcc 4.6.1).

File size: 49.2 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2001 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <stdarg.h>
25#include <stddef.h>
26#include <string.h>
27#include <ctype.h>
28#include <sys/types.h>
29
30#ifdef WITH_DATABASE
31
32/* define this if you want to debug the Oracle database support */
33/* #define DB_DEBUG */
34
35#define SH_REAL_SET
36
37#include "samhain.h"
38
39#include "sh_cat.h"
40#include "sh_error.h"
41#include "sh_utils.h"
42
43#undef FIL__
44#define FIL__ _("sh_database.c")
45
46typedef struct my_attr_
47{
48 char * attr;
49 char * attr_o;
50 int inHash;
51 int val;
52 int size;
53 int alen;
54 size_t off;
55} my_attr;
56
57typedef struct dbins_ {
58 struct dbins_ * next;
59 char host[64];
60 char time[20];
61 char msg[1024];
62 char sev[8];
63 char path[MAX_PATH_STORE+1];
64 char user[9];
65 char group[9];
66 char program[8];
67 char subroutine[16];
68 char status[12];
69 char hash[50];
70 char path_data[1024];
71 char hash_data[50];
72 char key_uid[64];
73 char key_uid_data[64];
74 char key_id[16];
75 char module[8];
76 char syscall[16];
77 char ip[SH_IP_BUF];
78 char tty[16];
79 char peer[64];
80 char fromhost[64];
81 char obj[1024];
82 char interface[64];
83 char ltime[64];
84 char dir[MAX_PATH_STORE+1];
85 char linked_path[MAX_PATH_STORE+1];
86 char service[64];
87 char facility[32];
88 char priority[32];
89 char syslog_msg[1024];
90
91 char mode_old[16];
92 char mode_new[16];
93 char attr_old[16];
94 char attr_new[16];
95 char device_old[16];
96 char device_new[16];
97 char owner_old[9];
98 char owner_new[9];
99 char group_old[9];
100 char group_new[9];
101 char ctime_old[20];
102 char ctime_new[20];
103 char atime_old[20];
104 char atime_new[20];
105 char mtime_old[20];
106 char mtime_new[20];
107 char chksum_old[50];
108 char chksum_new[50];
109 char link_old[MAX_PATH_STORE+1];
110 char link_new[MAX_PATH_STORE+1];
111 char acl_old[1024];
112 char acl_new[1024];
113
114 unsigned long ulong_data[20];
115
116 /*
117 long size_old;
118 long size_new;
119 long hardlinks_old;
120 long hardlinks_new;
121 long inode_old;
122 long inode_new;
123 */
124
125} dbins;
126
127static my_attr * attr_tab_srch = NULL;
128static int attr_tab_srch_siz = 0;
129
130static my_attr attr_tab[] = {
131 { NULL, N_("sev"), 0, 1, 8, 0, offsetof(struct dbins_, sev) },
132 { NULL, N_("tstamp"), 0, 2, 16, 0, offsetof(struct dbins_, time) },
133 { NULL, N_("remote_host"), 0, 3, 64, 0, offsetof(struct dbins_, host) },
134 { NULL, N_("msg"), 0, 4, 1024, 0, offsetof(struct dbins_, msg) },
135
136 { NULL, N_("path"), 0, 5,MAX_PATH_STORE+1, 0, offsetof(struct dbins_, path) },
137 /* username -> userid; replace (long) 'userid' - below - by 'dummy' */
138 { NULL, N_("userid"), 0, 6, 9, 0, offsetof(struct dbins_, user) },
139 { NULL, N_("group"), 0, 7, 9, 0, offsetof(struct dbins_, group) },
140 { NULL, N_("program"), 0, 8, 8, 0, offsetof(struct dbins_, program) },
141 { NULL, N_("subroutine"), 0, 9, 16, 0, offsetof(struct dbins_, subroutine)},
142 { NULL, N_("status"), 0, 10, 12, 0, offsetof(struct dbins_, status) },
143 { NULL, N_("hash"), 0, 11, 50, 0, offsetof(struct dbins_, hash) },
144 { NULL, N_("path_data"), 0, 12, 1024, 0, offsetof(struct dbins_, path_data) },
145 { NULL, N_("hash_data"), 0, 13, 50, 0, offsetof(struct dbins_, hash_data) },
146 { NULL, N_("key_uid"), 0, 14, 64, 0, offsetof(struct dbins_, key_uid) },
147 { NULL, N_("key_uid_data"),0, 15, 64, 0, offsetof(struct dbins_, key_uid_data)},
148 { NULL, N_("key_id"), 0, 16, 16, 0, offsetof(struct dbins_, key_id) },
149 { NULL, N_("module"), 0, 17, 8, 0, offsetof(struct dbins_, module) },
150 { NULL, N_("syscall"), 0, 19, 16, 0, offsetof(struct dbins_, syscall) },
151 { NULL, N_("ip"), 0, 20,SH_IP_BUF, 0, offsetof(struct dbins_, ip) },
152 { NULL, N_("tty"), 0, 21, 16, 0, offsetof(struct dbins_, tty) },
153 { NULL, N_("peer"), 0, 22, 64, 0, offsetof(struct dbins_, peer) },
154 { NULL, N_("obj"), 0, 23, 1024, 0, offsetof(struct dbins_, obj) },
155 { NULL, N_("interface"), 0, 24, 64, 0, offsetof(struct dbins_, interface)},
156 { NULL, N_("time"), 0, 25, 64, 0, offsetof(struct dbins_, ltime) },
157 { NULL, N_("dir"), 0, 26, MAX_PATH_STORE+1, 0, offsetof(struct dbins_, dir) },
158 { NULL, N_("linked_path"), 0, 27, MAX_PATH_STORE+1, 0, offsetof(struct dbins_, linked_path)},
159 { NULL, N_("service"), 0, 29, 64, 0, offsetof(struct dbins_, service)},
160 { NULL, N_("facility"), 0, 30, 32, 0, offsetof(struct dbins_, facility) },
161 { NULL, N_("priority"), 0, 31, 32, 0, offsetof(struct dbins_, priority) },
162 { NULL, N_("syslog_msg"), 0, 32, 1024, 0, offsetof(struct dbins_, syslog_msg) },
163
164 { NULL, N_("mode_old"), 0, 33, 16, 0, offsetof(struct dbins_, mode_old) },
165 { NULL, N_("mode_new"), 0, 34, 16, 0, offsetof(struct dbins_, mode_new) },
166 { NULL, N_("device_old"), 0, 35, 16, 0, offsetof(struct dbins_, device_old)},
167 { NULL, N_("device_new"), 0, 36, 16, 0, offsetof(struct dbins_, device_new)},
168 { NULL, N_("owner_old"), 0, 37, 9, 0, offsetof(struct dbins_, owner_old)},
169 { NULL, N_("owner_new"), 0, 38, 9, 0, offsetof(struct dbins_, owner_new)},
170 { NULL, N_("group_old"), 0, 39, 9, 0, offsetof(struct dbins_, group_old)},
171 { NULL, N_("group_new"), 0, 40, 9, 0, offsetof(struct dbins_, group_new)},
172 { NULL, N_("ctime_old"), 0, 41, 20, 0, offsetof(struct dbins_, ctime_old)},
173 { NULL, N_("ctime_new"), 0, 42, 20, 0, offsetof(struct dbins_, ctime_new)},
174 { NULL, N_("atime_old"), 0, 43, 20, 0, offsetof(struct dbins_, atime_old)},
175 { NULL, N_("atime_new"), 0, 44, 20, 0, offsetof(struct dbins_, atime_new)},
176 { NULL, N_("mtime_old"), 0, 45, 20, 0, offsetof(struct dbins_, mtime_old)},
177 { NULL, N_("mtime_new"), 0, 46, 20, 0, offsetof(struct dbins_, mtime_new)},
178 { NULL, N_("chksum_old"), 0, 47, 50, 0, offsetof(struct dbins_, chksum_old)},
179 { NULL, N_("chksum_new"), 0, 48, 50, 0, offsetof(struct dbins_, chksum_new)},
180 { NULL, N_("link_old"), 0, 49, MAX_PATH_STORE+1, 0, offsetof(struct dbins_, link_old)},
181 { NULL, N_("link_new"), 0, 50, MAX_PATH_STORE+1, 0, offsetof(struct dbins_, link_new)},
182
183 { NULL, N_("size_old"), 0, 51, 0, 0, 0 },
184 { NULL, N_("size_new"), 0, 52, 0, 0, 0 },
185 { NULL, N_("hardlinks_old"),0, 53, 0, 0, 0 },
186 { NULL, N_("hardlinks_new"),0, 54, 0, 0, 0 },
187 { NULL, N_("inode_old"), 0, 55, 0, 0, 0 },
188 { NULL, N_("inode_new"), 0, 56, 0, 0, 0 },
189
190 { NULL, N_("imode_old"), 0, 57, 0, 0, 0 },
191 { NULL, N_("imode_new"), 0, 58, 0, 0, 0 },
192 { NULL, N_("iattr_old"), 0, 59, 0, 0, 0 },
193 { NULL, N_("iattr_new"), 0, 60, 0, 0, 0 },
194 { NULL, N_("idevice_old"), 0, 61, 0, 0, 0 },
195 { NULL, N_("idevice_new"), 0, 62, 0, 0, 0 },
196 { NULL, N_("iowner_old"), 0, 63, 0, 0, 0 },
197 { NULL, N_("iowner_new"), 0, 64, 0, 0, 0 },
198 { NULL, N_("igroup_old"), 0, 65, 0, 0, 0 },
199 { NULL, N_("igroup_new"), 0, 66, 0, 0, 0 },
200
201 { NULL, N_("port"), 0, 67, 0, 0, 0 },
202 { NULL, N_("return_code"), 0, 68, 0, 0, 0 },
203 /* { NULL, N_("userid"), 0, 69, 0, 0 }, old 'userid', 1.8.1 */
204
205 { NULL, N_("host"), 0, 70, 64, 0, offsetof(struct dbins_, fromhost)},
206 { NULL, N_("attr_old"), 0, 71, 16, 0, offsetof(struct dbins_, attr_old)},
207 { NULL, N_("attr_new"), 0, 72, 16, 0, offsetof(struct dbins_, attr_new)},
208 { NULL, N_("acl_old"), 0, 73, 1024, 0, offsetof(struct dbins_, acl_old)},
209 { NULL, N_("acl_new"), 0, 74, 1024, 0, offsetof(struct dbins_, acl_new)},
210
211 { NULL, NULL, 0, 0, 0, 0, 0 }
212};
213
214#define SH_SLOT_HOST 70
215#define SH_SLOT_GROUP 7
216#define START_SEC_LONGS 51
217#define END_SEC_LONGS 68
218
219#if defined(HAVE_INT_32)
220typedef unsigned int uint32;
221#elif defined(HAVE_LONG_32)
222typedef unsigned long uint32;
223#elif defined(HAVE_SHORT_32)
224typedef unsigned short uint32;
225#else
226#error No 32 byte type found !
227#endif
228
229typedef unsigned char uint8;
230
231typedef struct md5_ctx
232{
233 uint32 A;
234 uint32 B;
235 uint32 C;
236 uint32 D;
237
238 uint32 total[2];
239 uint32 buflen;
240 char buffer[128];
241} md5Param;
242
243
244typedef unsigned char sh_byte;
245
246
247extern int md5Reset(register md5Param* p);
248extern int md5Update(md5Param* p, const sh_byte* data, int size);
249extern int md5Digest(md5Param* p, uint32* data);
250
251static char db_name[64] = "";
252static char db_table[64] = "";
253static char db_host[64] = "";
254static char db_user[64] = "";
255static char db_password[64] = "";
256
257static int sh_persistent_dbconn = S_TRUE;
258
259int sh_database_use_persistent (const char * str)
260{
261 return sh_util_flagval (str, &sh_persistent_dbconn);
262}
263
264static int insert_value (char * ptr, const char * str)
265{
266 if (!ptr || !str)
267 return -1;
268 if (strlen(str) > 63)
269 return -1;
270 (void) sl_strlcpy(ptr, str, 64);
271 return 0;
272}
273
274static void init_db_entry (dbins * ptr)
275{
276 memset (ptr, (int) '\0', sizeof(dbins));
277 ptr->next = NULL;
278 return;
279}
280
281
282int sh_database_set_database (const char * str)
283{
284 return insert_value (db_name, str);
285}
286int sh_database_set_table (const char * str)
287{
288 return insert_value (db_table, str);
289}
290int sh_database_set_host (const char * str)
291{
292 return insert_value (db_host, str);
293}
294int sh_database_set_user (const char * str)
295{
296 return insert_value (db_user, str);
297}
298int sh_database_set_password (const char * str)
299{
300 return insert_value (db_password, str);
301}
302
303/******************************************************************
304 *
305 * Oracle and unixODBC stuff, only Oracle tested untested
306 *
307 * Based on the code in the snort output plugin (spo_database.c).
308 * Copyright/license statement in spo_database.c:
309 *
310 * Portions Copyright (C) 2000,2001,2002 Carnegie Mellon University
311 * Copyright (C) 2001 Jed Pickel <jed@pickel.net>
312 * Portions Copyright (C) 2001 Andrew R. Baker <andrewb@farm9.com>
313 *
314 * This program is free software; you can redistribute it and/or modify
315 * it under the terms of the GNU General Public License as published by
316 * the Free Software Foundation; either version 2 of the License, or
317 * (at your option) any later version.
318 *
319 * This program is distributed in the hope that it will be useful,
320 * but WITHOUT ANY WARRANTY; without even the implied warranty of
321 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
322 * GNU General Public License for more details.
323 *
324 * You should have received a copy of the GNU General Public License
325 * along with this program; if not, write to the Free Software
326 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
327 *
328 ******************************************************************/
329#ifdef WITH_ODBC
330
331#include <sql.h>
332#include <sqlext.h>
333#include <sqltypes.h>
334
335static SQLHENV u_handle;
336static SQLHDBC u_connection;
337static SQLHSTMT u_statement;
338static SQLINTEGER u_col;
339static SQLINTEGER u_rows;
340
341void sh_database_reset()
342{
343 return;
344}
345
346static
347int sh_database_query (char * query, /*@out@*/ long * id)
348{
349 static int fatal_error = 0;
350 int result = 0;
351 char row_query[128];
352 long result_call;
353
354 SL_ENTER(_("sh_database_query"));
355
356 *id = 0;
357
358 if (fatal_error == 1)
359 {
360 SL_RETURN((-1), _("sh_database_query"));
361 }
362
363 /* Connect
364 */
365 if (db_name[0] == '\0')
366 sl_strlcpy(db_name, _("samhain"), 64);
367
368 if (db_user[0] == '\0')
369 sl_strlcpy(db_user, _("samhain"), 64);
370
371 result_call = SQLAllocEnv(&u_handle);
372 if ((result_call != SQL_SUCCESS) && (result_call != SQL_SUCCESS_WITH_INFO))
373 {
374 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, result_call,
375 MSG_E_SUBGEN,
376 _("Error in SQLAllocEnv when connecting to ODBC data source"),
377 _("sh_database_query"));
378 fatal_error = 1;
379 SL_RETURN((-1), _("sh_database_query"));
380 }
381 result_call = SQLAllocConnect(u_handle, &u_connection);
382 if ((result_call != SQL_SUCCESS) && (result_call != SQL_SUCCESS_WITH_INFO))
383 {
384 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, result_call,
385 MSG_E_SUBGEN,
386 _("Error in SQLAllocEnv when connecting to ODBC data source"),
387 _("sh_database_query"));
388 fatal_error = 1;
389 SL_RETURN((-1), _("sh_database_query"));
390 }
391 result_call = SQLConnect(u_connection, db_name, SQL_NTS,
392 db_user, SQL_NTS, db_password, SQL_NTS);
393 if ((result_call != SQL_SUCCESS) && (result_call != SQL_SUCCESS_WITH_INFO))
394 {
395 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, result_call,
396 MSG_E_SUBGEN,
397 _("Error in SQLAllocEnv when connecting to ODBC data source"),
398 _("sh_database_query"));
399 fatal_error = 1;
400 SL_RETURN((-1), _("sh_database_query"));
401 }
402
403 /* Insert
404 */
405 result_call = SQLAllocStmt(u_connection, &u_statement);
406 if ((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO))
407 {
408 result_call = SQLPrepare(u_statement, query, SQL_NTS);
409 if ((result_call == SQL_SUCCESS) ||
410 (result_call == SQL_SUCCESS_WITH_INFO))
411 {
412 result_call = SQLExecute(u_statement);
413 if((result_call == SQL_SUCCESS) ||
414 (result_call == SQL_SUCCESS_WITH_INFO))
415 {
416 result = 1;
417 }
418 }
419 }
420
421 if (result == 0)
422 {
423 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
424 _("Error inserting into ODBC data source"),
425 _("sh_database_query"));
426 goto odbc_disconnect;
427 }
428
429 /* Select
430 */
431 result = 0;
432
433 sl_strlcpy (row_query, _("SELECT MAX(log_index) FROM "), 128);
434 sl_strlcat (row_query, db_table, 128);
435
436 result_call = SQLAllocStmt(u_connection, &u_statement);
437 if ((result_call == SQL_SUCCESS) ||
438 (result_call == SQL_SUCCESS_WITH_INFO))
439 {
440 result_call = SQLPrepare(u_statement, row_query, SQL_NTS);
441 if ((result_call == SQL_SUCCESS) ||
442 (result_call == SQL_SUCCESS_WITH_INFO))
443 {
444 result_call = SQLExecute(u_statement);
445 if ((result_call == SQL_SUCCESS) ||
446 (result_call == SQL_SUCCESS_WITH_INFO))
447 {
448 result_call = SQLRowCount(u_statement, &u_rows);
449 if ((result_call == SQL_SUCCESS) ||
450 (result_call == SQL_SUCCESS_WITH_INFO))
451 {
452 if((u_rows) && (u_rows == 1))
453 {
454 result_call = SQLFetch(u_statement);
455 if ((result_call == SQL_SUCCESS) ||
456 (result_call == SQL_SUCCESS_WITH_INFO))
457 {
458 result_call = SQLGetData(u_statement, 1,
459 SQL_INTEGER, &u_col,
460 sizeof(u_col), NULL);
461 if ((result_call == SQL_SUCCESS) ||
462 (result_call == SQL_SUCCESS_WITH_INFO))
463 {
464 *id = (long int) u_col;
465 result = 1;
466 }
467 }
468 }
469 }
470 }
471 }
472 }
473
474 if (result == 0)
475 {
476 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
477 _("Error selecting MAX(log_index) from ODBC data source"),
478 _("sh_database_query"));
479 }
480
481 odbc_disconnect:
482 SQLFreeHandle(SQL_HANDLE_STMT, u_statement);
483 SQLDisconnect(u_connection);
484 SQLFreeHandle(SQL_HANDLE_DBC, u_connection);
485 SQLFreeHandle(SQL_HANDLE_ENV, u_handle);
486
487 SL_RETURN(((result == 0) ? -1 : 0), _("sh_database_query"));
488
489}
490
491/* #ifdef WITH_ODBC */
492#endif
493
494#ifdef WITH_ORACLE
495
496#include <oci.h>
497
498static OCIDefine * o_define;
499static OCIEnv * o_environment;
500static OCISvcCtx * o_servicecontext;
501static OCIError * o_error = NULL;
502static OCIStmt * o_statement;
503static OCIBind * o_bind = (OCIBind *) 0;
504static text o_errormsg[512];
505static sb4 o_errorcode;
506
507static int connected = 0;
508
509void sh_database_reset()
510{
511 if (connected == 1)
512 {
513 OCILogoff(o_servicecontext, o_error);
514 OCIHandleFree((dvoid *) o_statement, OCI_HTYPE_STMT);
515 OCIHandleFree((dvoid *) o_servicecontext, OCI_HTYPE_SVCCTX);
516 OCIHandleFree((dvoid *) o_error, OCI_HTYPE_ERROR);
517 o_error = NULL;
518 }
519 connected = 0;
520 return;
521}
522
523static char * sh_stripnl (char * str)
524{
525 size_t len = sl_strlen(str);
526 if (len > 0)
527 {
528 if (str[len-1] == '\n')
529 str[len-1] = '\0';
530 }
531 return str;
532}
533
534static
535int sh_database_query (char * query, /*@out@*/ long * id)
536{
537 static int bad_init = 0;
538 int result = 0;
539 char row_query[128];
540 int retry = 0;
541
542 SL_ENTER(_("sh_database_query"));
543
544 *id = 0;
545
546 if (bad_init == 1) {
547 SL_RETURN(-1, _("sh_database_query"));
548 }
549 else if (connected == 1) {
550 goto oracle_connected;
551 }
552
553 /*
554 * Connect
555 */
556#define PRINT_ORACLE_ERR(func_name) \
557 do { \
558 OCIErrorGet(o_error, 1, NULL, &o_errorcode, \
559 o_errormsg, sizeof(o_errormsg), \
560 OCI_HTYPE_ERROR); \
561 sh_stripnl (o_errormsg); \
562 sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, \
563 o_errormsg, _("sh_database_query")); \
564 sl_snprintf(row_query, 127, \
565 _("%s: Connection to database '%s' failed"), \
566 func_name, db_name); \
567 sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN, \
568 row_query, _("sh_database_query")); \
569 bad_init = 1; \
570 SL_RETURN(-1, _("sh_database_query")); \
571 } while (1 == 0)
572
573 oracle_doconnect:
574
575 if (!getenv("ORACLE_HOME")) /* flawfinder: ignore */
576 {
577 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
578 _("ORACLE_HOME environment variable not set"),
579 _("sh_database_query"));
580 }
581 if (db_name[0] == '\0')
582 {
583 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
584 _("database name not set, using default 'samhain'"),
585 _("sh_database_query"));
586 sl_strlcpy(db_name, _("samhain"), 64);
587 }
588 if (db_user[0] == '\0')
589 {
590 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
591 _("database user not set, using default 'samhain'"),
592 _("sh_database_query"));
593 sl_strlcpy(db_user, _("samhain"), 64);
594 }
595 if (db_password[0] == '\0')
596 {
597 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
598 _("database password not set, cannot proceed"),
599 _("sh_database_query"));
600 bad_init = 1;
601 SL_RETURN(-1, _("sh_database_query"));
602 }
603
604
605#ifdef DB_DEBUG
606 sl_snprintf(row_query, 127,
607 _("Conncting to oracle database '%s'"),
608 db_name);
609 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
610 row_query,
611 _("sh_database_query"));
612#endif
613
614 /* a) Oracle says use OCIEnvCreate instead of OCIInitialize/OCIEnvcreate
615 * b) why two times OCIEnvInit() ???
616 */
617 if (OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL))
618 PRINT_ORACLE_ERR("OCIInitialize");
619
620 if (OCIEnvInit(&o_environment, OCI_DEFAULT, 0, NULL))
621 PRINT_ORACLE_ERR("OCIEnvInit");
622
623 if (OCIEnvInit(&o_environment, OCI_DEFAULT, 0, NULL))
624 PRINT_ORACLE_ERR("OCIEnvInit (2)");
625
626 /* allocate and initialize the error handle
627 */
628 if (OCIHandleAlloc(o_environment, (dvoid **)&o_error,
629 OCI_HTYPE_ERROR, (size_t) 0, NULL))
630 PRINT_ORACLE_ERR("OCIHandleAlloc");
631
632 /* logon and allocate the service context handle
633 */
634 if (OCILogon(o_environment, o_error, &o_servicecontext,
635 (OraText*) db_user, sl_strlen(db_user),
636 (OraText*) db_password, sl_strlen(db_password),
637 (OraText*) db_name, sl_strlen(db_name)))
638 {
639 OCIErrorGet(o_error, 1, NULL, &o_errorcode,
640 o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR);
641 sh_stripnl (o_errormsg);
642 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
643 o_errormsg,
644 _("sh_database_query"));
645 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
646 _("check database is listed in tnsnames.ora"),
647 _("sh_database_query"));
648 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
649 _("check tnsnames.ora readable"),
650 _("sh_database_query"));
651 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
652 _("check database accessible with sqlplus"),
653 _("sh_database_query"));
654 sl_snprintf(row_query, 127,
655 _("OCILogon: Connection to database '%s' failed"),
656 db_name);
657 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
658 row_query, _("sh_database_query"));
659 bad_init = 1;
660 SL_RETURN(-1, _("sh_database_query"));
661 }
662
663 if (OCIHandleAlloc(o_environment, (dvoid **)&o_statement,
664 OCI_HTYPE_STMT, 0, NULL))
665 PRINT_ORACLE_ERR("OCIHandleAlloc (2)");
666
667 /* Flag connection status
668 */
669 connected = 1;
670
671 oracle_connected:
672
673 /* Get row index
674 */
675 sl_strlcpy (row_query, _("SELECT log_log_index_seq.NEXTVAL FROM dual"), 128);
676
677#ifdef DB_DEBUG
678 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
679 row_query,
680 _("sh_database_query"));
681#endif
682
683 if (OCIStmtPrepare(o_statement, o_error,
684 (OraText*) row_query, sl_strlen(row_query),
685 OCI_NTV_SYNTAX, OCI_DEFAULT))
686 {
687 OCIErrorGet(o_error, 1, NULL,
688 &o_errorcode, o_errormsg, sizeof(o_errormsg),
689 OCI_HTYPE_ERROR);
690 sh_stripnl (o_errormsg);
691 sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN,
692 o_errormsg,
693 _("sh_database_query"));
694 if (retry == 0 &&
695 (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9)))
696 {
697 ++retry; sh_database_reset(); goto oracle_doconnect;
698 }
699 goto err_out;
700 }
701
702 if (OCIStmtExecute(o_servicecontext, o_statement, o_error,
703 0, 0, NULL, NULL, OCI_DEFAULT))
704 {
705 OCIErrorGet(o_error, 1, NULL,
706 &o_errorcode, o_errormsg, sizeof(o_errormsg),
707 OCI_HTYPE_ERROR);
708 sh_stripnl (o_errormsg);
709 sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN,
710 o_errormsg,
711 _("sh_database_query"));
712 if (retry == 0 &&
713 (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9)))
714 {
715 ++retry; sh_database_reset(); goto oracle_doconnect;
716 }
717 goto err_out;
718 }
719
720 if (OCIDefineByPos (o_statement, &o_define, o_error, 1,
721 &result, sizeof(result),
722 SQLT_INT, 0, 0, 0, OCI_DEFAULT))
723 {
724 OCIErrorGet(o_error, 1, NULL,
725 &o_errorcode, o_errormsg, sizeof(o_errormsg),
726 OCI_HTYPE_ERROR);
727 sh_stripnl (o_errormsg);
728 sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN,
729 o_errormsg,
730 _("sh_database_query"));
731 if (retry == 0 &&
732 (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9)))
733 {
734 ++retry; sh_database_reset(); goto oracle_doconnect;
735 }
736 goto err_out;
737 }
738 if (OCIStmtFetch (o_statement, o_error, 1, OCI_FETCH_NEXT, OCI_DEFAULT))
739 {
740 OCIErrorGet(o_error, 1, NULL,
741 &o_errorcode, o_errormsg, sizeof(o_errormsg),
742 OCI_HTYPE_ERROR);
743 sh_stripnl (o_errormsg);
744 sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN,
745 o_errormsg,
746 _("sh_database_query"));
747 if (retry == 0 &&
748 (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9)))
749 {
750 ++retry; sh_database_reset(); goto oracle_doconnect;
751 }
752 goto err_out;
753 }
754
755#ifdef DB_DEBUG
756 sl_snprintf(row_query, 127, _("Returned value: %d"), result);
757 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
758 row_query,
759 _("sh_database_query"));
760#endif
761
762 *id = result;
763
764 /* do the insert
765 */
766#ifdef DB_DEBUG
767 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
768 query,
769 _("sh_database_query"));
770#endif
771
772 if (OCIStmtPrepare(o_statement, o_error,
773 (OraText*) query, sl_strlen(query),
774 OCI_NTV_SYNTAX, OCI_DEFAULT))
775 {
776 OCIErrorGet(o_error, 1, NULL,
777 &o_errorcode, o_errormsg, sizeof(o_errormsg),
778 OCI_HTYPE_ERROR);
779 sh_stripnl (o_errormsg);
780 sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN,
781 o_errormsg,
782 _("sh_database_query"));
783 if (retry == 0 &&
784 (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9)))
785 {
786 ++retry; sh_database_reset(); goto oracle_doconnect;
787 }
788 goto err_out;
789 }
790
791 if (OCIBindByPos(o_statement, &o_bind, o_error, 1,
792 (dvoid *) &result, (sword) sizeof(result), SQLT_INT,
793 (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT))
794 {
795 OCIErrorGet(o_error, 1, NULL,
796 &o_errorcode, o_errormsg, sizeof(o_errormsg),
797 OCI_HTYPE_ERROR);
798 sh_stripnl (o_errormsg);
799 sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN,
800 o_errormsg,
801 _("sh_database_query"));
802 if (retry == 0 &&
803 (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9)))
804 {
805 ++retry; sh_database_reset(); goto oracle_doconnect;
806 }
807 goto err_out;
808 }
809
810 if (OCIStmtExecute(o_servicecontext,
811 o_statement, o_error, 1, 0,
812 NULL, NULL, OCI_COMMIT_ON_SUCCESS))
813 {
814 OCIErrorGet(o_error, 1, NULL,
815 &o_errorcode, o_errormsg, sizeof(o_errormsg),
816 OCI_HTYPE_ERROR);
817 sh_stripnl (o_errormsg);
818 sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN,
819 o_errormsg,
820 _("sh_database_query"));
821 if (retry == 0 &&
822 (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9)))
823 {
824 ++retry; sh_database_reset(); goto oracle_doconnect;
825 }
826 goto err_out;
827 }
828
829#ifdef DB_DEBUG
830 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
831 _("No error on insert"),
832 _("sh_database_query"));
833#endif
834
835 if (sh_persistent_dbconn == S_FALSE)
836 {
837 OCILogoff(o_servicecontext, o_error);
838 OCIHandleFree((dvoid *) o_statement, OCI_HTYPE_STMT);
839 OCIHandleFree((dvoid *) o_servicecontext, OCI_HTYPE_SVCCTX);
840 OCIHandleFree((dvoid *) o_error, OCI_HTYPE_ERROR);
841 o_error = NULL;
842 connected = 0;
843 }
844 SL_RETURN(0, _("sh_database_query"));
845
846 err_out:
847 /*
848 * Error
849 */
850 if (sh_persistent_dbconn == S_FALSE)
851 {
852 OCILogoff(o_servicecontext, o_error);
853 OCIHandleFree((dvoid *) o_statement, OCI_HTYPE_STMT);
854 OCIHandleFree((dvoid *) o_servicecontext, OCI_HTYPE_SVCCTX);
855 OCIHandleFree((dvoid *) o_error, OCI_HTYPE_ERROR);
856 o_error = NULL;
857 connected = 0;
858 }
859 SL_RETURN(-1, _("sh_database_query"));
860}
861
862/* #ifdef WITH_ORACLE */
863#endif
864
865#ifdef WITH_POSTGRES
866/******************************************************************
867 *
868 * Postgresql stuff, tested
869 *
870 ******************************************************************/
871
872#if defined(HAVE_PGSQL_LIBPQ_FE_H)
873#include <pgsql/libpq-fe.h>
874#elif defined(HAVE_POSTGRESQL_LIBPQ_FE_H)
875#include <postgresql/libpq-fe.h>
876#else
877#if !defined(USE_UNO)
878#include <libpq-fe.h>
879#else
880#include <postgresql/libpq-fe.h>
881#endif
882#endif
883
884static int connection_status = S_FALSE;
885
886void sh_database_reset()
887{
888 connection_status = S_FALSE;
889 return;
890}
891
892static
893int sh_database_query (char * query, /*@out@*/ long * id)
894{
895 char conninfo[256];
896 char * p;
897 static PGconn * conn = NULL;
898 PGresult * res;
899 unsigned int i;
900 const char * params[1];
901 char id_param[32];
902 static SH_TIMEOUT sh_timer = { 0, 3600, S_TRUE };
903
904 SL_ENTER(_("sh_database_query"));
905
906 *id = 0;
907
908 p = &conninfo[0];
909
910 if (db_host[0] == '\0')
911 sl_strlcpy(db_host, _("localhost"), 64);
912 if (db_name[0] == '\0')
913 sl_strlcpy(db_name, _("samhain"), 64);
914 if (db_user[0] == '\0')
915 sl_strlcpy(db_user, _("samhain"), 64);
916
917 if (db_host[0] != '\0' && NULL != strchr(db_host, '.'))
918 {
919 sl_snprintf(p, 255, "hostaddr=%s ", db_host);
920 p = &conninfo[strlen(conninfo)];
921 }
922 if (db_name[0] != '\0')
923 {
924 sl_snprintf(p, 255 - strlen(conninfo), "dbname=%s ", db_name);
925 p = &conninfo[strlen(conninfo)];
926 }
927
928 if (db_user[0] != '\0')
929 {
930 sl_snprintf(p, 255 - strlen(conninfo), "user=%s ", db_user);
931 p = &conninfo[strlen(conninfo)];
932 }
933
934 if (db_password[0] != '\0')
935 {
936 sl_snprintf(p, 255 - strlen(conninfo), "password=%s ", db_password);
937 }
938
939 if (connection_status == S_FALSE)
940 {
941 if (conn)
942 PQfinish(conn);
943 conn = NULL;
944 conn = PQconnectdb(conninfo);
945 }
946 else
947 {
948 if (PQstatus(conn) == CONNECTION_BAD)
949 PQreset(conn);
950 }
951
952 if ((conn == NULL) || (PQstatus(conn) == CONNECTION_BAD))
953 {
954 connection_status = S_FALSE;
955
956 sh_timer.flag_ok = S_FALSE;
957 if (S_TRUE == sh_util_timeout_check(&sh_timer))
958 {
959 goto err_out;
960 }
961 else
962 {
963 if (conn)
964 PQfinish(conn);
965 conn = NULL;
966 SL_RETURN(0, _("sh_database_query"));
967 }
968 }
969 connection_status = S_TRUE;
970
971
972 /* get the unique row index
973 */
974 res = PQexec(conn, _("SELECT NEXTVAL('log_log_index_seq')"));
975 if (PQresultStatus(res) != PGRES_TUPLES_OK)
976 {
977 PQclear(res);
978 goto err_out;
979 }
980
981 *id = atoi (PQgetvalue(res, 0, 0));
982 PQclear(res);
983
984 sl_snprintf(id_param, 32, "%ld", *id);
985 params[0] = id_param;
986
987 /* do the insert
988 */
989 res = PQexecParams(conn, query, 1, NULL, params, NULL, NULL, 1);
990 if (PQresultStatus(res) != PGRES_COMMAND_OK)
991 {
992 PQclear(res);
993 goto err_out;
994 }
995 PQclear(res);
996
997 if (S_FALSE == sh_persistent_dbconn)
998 {
999 if (conn)
1000 PQfinish(conn);
1001 conn = NULL;
1002 connection_status = S_FALSE;
1003 }
1004 SL_RETURN(0, _("sh_database_query"));
1005
1006
1007 err_out:
1008 if (conn)
1009 {
1010 p = PQerrorMessage(conn);
1011 for (i = 0; i < sl_strlen(p); ++i)
1012 if (p[i] == '\n') p[i] = ' ';
1013 }
1014 else
1015 {
1016 p = NULL;
1017 }
1018 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
1019 (p == NULL ? _("(null)") : p),
1020 _("sh_database_query"));
1021 if (conn)
1022 PQfinish(conn);
1023 conn = NULL;
1024 connection_status = S_FALSE;
1025 SL_RETURN(-1, _("sh_database_query"));
1026}
1027#endif
1028
1029
1030#ifdef WITH_MYSQL
1031
1032#ifdef HAVE_MYSQL_MYSQL_H
1033#include <mysql/mysql.h>
1034#else
1035#include <mysql.h>
1036#endif
1037
1038extern int flag_err_debug;
1039
1040static int connection_status = S_FALSE;
1041
1042void sh_database_reset(void)
1043{
1044 connection_status = S_FALSE;
1045 return;
1046}
1047
1048static
1049int sh_database_query (char * query, /*@out@*/ long * id)
1050{
1051 int status = 0;
1052 const char * p;
1053 static MYSQL * db_conn = NULL;
1054 static SH_TIMEOUT sh_timer = { 0, 3600, S_TRUE };
1055
1056 SL_ENTER(_("sh_database_query"));
1057
1058 *id = 0;
1059
1060 if (query == NULL)
1061 {
1062 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1063 _("NULL query"),
1064 _("sh_database_query"));
1065 SL_RETURN(0, _("sh_database_query"));
1066 }
1067
1068 if (db_host[0] == '\0')
1069 (void) sl_strlcpy(db_host, _("localhost"), 64);
1070 if (db_name[0] == '\0')
1071 (void) sl_strlcpy(db_name, _("samhain"), 64);
1072 if (db_user[0] == '\0')
1073 (void) sl_strlcpy(db_user, _("samhain"), 64);
1074
1075 if ((db_conn == NULL) || (connection_status == S_FALSE))
1076 {
1077 if (db_conn)
1078 {
1079 mysql_close(db_conn);
1080 db_conn = NULL;
1081 }
1082 connection_status = S_FALSE;
1083
1084 db_conn = mysql_init(NULL);
1085 if (NULL == db_conn)
1086 {
1087 p = NULL; status = 0;
1088 sh_timer.flag_ok = S_FALSE;
1089 if (S_TRUE == sh_util_timeout_check(&sh_timer))
1090 {
1091 goto alt_out;
1092 }
1093 else
1094 {
1095 SL_RETURN(0, _("sh_database_query"));
1096 }
1097 }
1098
1099 /* Read in defaults from /etc/my.cnf and associated files,
1100 * suggested by arjones at simultan dyndns org
1101 * see: - http://dev.mysql.com/doc/refman/5.0/en/option-files.html
1102 * for the my.cnf format,
1103 * - http://dev.mysql.com/doc/refman/5.0/en/mysql-options.html
1104 * for possible options
1105 * We don't check the return value because it's useless (failure due
1106 * to lack of access permission is not reported).
1107 */
1108#if !defined(__x86_64__)
1109 /*
1110 * libmysql segfaults on x86-64 if this is used
1111 */
1112 mysql_options(db_conn, MYSQL_READ_DEFAULT_GROUP, _("samhain"));
1113#endif
1114
1115 status = 0;
1116
1117 if (NULL == mysql_real_connect(db_conn,
1118 db_host[0] == '\0' ? NULL : db_host,
1119 db_user[0] == '\0' ? NULL : db_user,
1120 db_password[0] == '\0' ? NULL : db_password,
1121 db_name[0] == '\0' ? NULL : db_name,
1122 0, NULL, 0))
1123 {
1124 sh_timer.flag_ok = S_FALSE;
1125 if (S_TRUE == sh_util_timeout_check(&sh_timer))
1126 {
1127 goto err_out;
1128 }
1129 else
1130 {
1131 SL_RETURN(0, _("sh_database_query"));
1132 }
1133 }
1134 connection_status = S_TRUE;
1135 }
1136 else
1137 {
1138 if (0 != mysql_ping(db_conn))
1139 {
1140 connection_status = S_FALSE;
1141 sh_timer.flag_ok = S_FALSE;
1142 if (S_TRUE == sh_util_timeout_check(&sh_timer))
1143 {
1144 goto err_out;
1145 }
1146 else
1147 {
1148 SL_RETURN(0, _("sh_database_query"));
1149 }
1150 }
1151 }
1152
1153 if (0 != mysql_query(db_conn, query))
1154 {
1155 goto err_out;
1156 }
1157
1158 if (flag_err_debug == SL_TRUE)
1159 {
1160 p = mysql_info (db_conn);
1161 if (p != NULL)
1162 {
1163 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1164 p,
1165 _("sh_database_query"));
1166 }
1167 }
1168
1169 *id = (long) mysql_insert_id(db_conn);
1170 if (S_FALSE == sh_persistent_dbconn)
1171 {
1172 if (db_conn)
1173 mysql_close(db_conn);
1174 db_conn = NULL;
1175 connection_status = S_FALSE;
1176 }
1177 SL_RETURN(0, _("sh_database_query"));
1178
1179 err_out:
1180
1181 if (db_conn)
1182 {
1183 p = mysql_error (db_conn);
1184 status = (int) mysql_errno (db_conn);
1185 }
1186 else
1187 {
1188 p = NULL; p = 0;
1189 }
1190
1191 alt_out:
1192
1193 *id = 0;
1194 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1195 (p == NULL ? _("(null)") : p),
1196 _("sh_database_query"));
1197 if (db_conn)
1198 mysql_close(db_conn);
1199 db_conn = NULL;
1200 connection_status = S_FALSE;
1201 SL_RETURN(status, _("sh_database_query"));
1202}
1203#endif
1204
1205static
1206char * null_or_val (char * end, char * val, int * size, int flag)
1207{
1208 long len;
1209
1210 if (!((end == NULL) || (val == NULL) || (size == NULL)))
1211 {
1212 if (val[0] != '\0')
1213 {
1214 if (*size > 1)
1215 {
1216 *end = ','; ++end; (*size) -= 1;
1217 if (flag == 1) { *end = '\''; ++end; (*size) -= 1; }
1218 *end = '\0';
1219 }
1220 len = (long) strlen(val);
1221 if ((long) *size > (len+1))
1222 {
1223 (void) sl_strlcat(end, val, (size_t) *size);
1224 end += len; (*size) -= len;
1225 if (flag == 1) { *end = '\''; ++end; (*size) -= 1; }
1226 *end = '\0';
1227 }
1228 }
1229 }
1230
1231 return end;
1232}
1233
1234#define SH_QUERY_MAX SH_MSG_BUF
1235/* define SH_QUERY_MAX 16383 */
1236
1237static
1238long sh_database_entry (dbins * db_entry, long id)
1239{
1240 /* This does not need to be re-entrant
1241 */
1242 char * query;
1243 static char columns[1024];
1244 char * values;
1245
1246 long the_id;
1247 int size;
1248 char * end;
1249 int c_size;
1250 char * c_end;
1251 char * p;
1252 int i;
1253 char num[64];
1254
1255 md5Param crc;
1256 unsigned char md5buffer[16];
1257 char md5out[33];
1258 int cnt;
1259
1260 size_t len_val;
1261 size_t len_col;
1262
1263 SL_ENTER(_("sh_database_entry"));
1264
1265 query = SH_ALLOC(SH_QUERY_MAX+1);
1266 values = SH_ALLOC(SH_QUERY_MAX+1);
1267
1268 (void) md5Reset(&crc);
1269
1270 if (db_entry->host[0] == '\0')
1271 {
1272 if (sh.host.name[0] == '\0')
1273 (void) strcpy (db_entry->host, _("localhost")); /* known to fit */
1274 else
1275 (void) sl_strlcpy (db_entry->host, sh.host.name, 64);
1276 }
1277
1278 /*@-bufferoverflowhigh@*/
1279 if (id >= 0)
1280 sprintf(num, "%ld", id); /* known to fit */
1281 /*@+bufferoverflowhigh@*/
1282
1283#if defined(WITH_ORACLE)
1284 /* Oracle needs some help for the time format (fix by Michael Somers)
1285 */
1286 (void)
1287 sl_snprintf (values, SH_QUERY_MAX,
1288 _("(:1,%s,%c%s%c,to_date(%c%s%c,'YYYY-MM-DD HH24:MI:SS'),%c%s%c,%c%s%c"),
1289 id >= 0 ? num : _("NULL"),
1290 '\'', db_entry->host,'\'',
1291 '\'', db_entry->time,'\'',
1292 '\'', db_entry->sev, '\'',
1293 '\'',
1294 (db_entry->msg[0] == '\0' ? _("NULL") : db_entry->msg),
1295 '\'');
1296 (void) sl_snprintf (columns, 1023,
1297 _("(log_index,log_ref,log_host,log_time,log_sev,log_msg"));
1298#elif defined(WITH_POSTGRES)
1299 /* Prepare query for PQexecParams
1300 */
1301 (void)
1302 sl_snprintf (values, SH_QUERY_MAX,
1303 _("($1,%s,%c%s%c,%c%s%c,%c%s%c,%c%s%c"),
1304 id >= 0 ? num : _("NULL"),
1305 '\'', db_entry->host,'\'',
1306 '\'', db_entry->time,'\'',
1307 '\'', db_entry->sev, '\'',
1308 '\'',
1309 (db_entry->msg[0] == '\0' ? _("NULL") : db_entry->msg),
1310 '\'');
1311 (void) sl_snprintf (columns, 1023,
1312 _("(log_index,log_ref,log_host,log_time,log_sev,log_msg"));
1313#else
1314 (void)
1315 sl_snprintf (values, SH_QUERY_MAX, _("(%s,%c%s%c,%c%s%c,%c%s%c,%c%s%c"),
1316 id >= 0 ? num : _("NULL"),
1317 '\'', db_entry->host,'\'',
1318 '\'', db_entry->time,'\'',
1319 '\'', db_entry->sev, '\'',
1320 '\'',
1321 (db_entry->msg[0] == '\0' ? _("NULL") : db_entry->msg),
1322 '\'');
1323 (void) sl_snprintf (columns, 1023,
1324 _("(log_ref,log_host,log_time,log_sev,log_msg"));
1325#endif
1326
1327
1328 /*@-type@*//* byte* versus char[..] */
1329 if (attr_tab[0].inHash == 1)
1330 (void) md5Update(&crc, (sh_byte*) db_entry->sev,
1331 (int) strlen(db_entry->sev));
1332 if (attr_tab[1].inHash == 1)
1333 (void) md5Update(&crc, (sh_byte*) db_entry->time,
1334 (int) strlen(db_entry->time));
1335 if (attr_tab[2].inHash == 1)
1336 (void) md5Update(&crc, (sh_byte*) db_entry->host,
1337 (int) strlen(db_entry->host));
1338 if (attr_tab[3].inHash == 1 && db_entry->msg[0] != '\0')
1339 (void) md5Update(&crc, (sh_byte*) db_entry->msg,
1340 (int) strlen(db_entry->sev));
1341 /*@+type@*/
1342
1343 len_val = strlen(values);
1344 size = (int) (SH_QUERY_MAX - len_val);
1345 end = values + len_val;
1346
1347 len_col = strlen(columns);
1348 c_size = 1023 - (int) len_col; /* sizeof(colums) == 1024 */
1349 c_end = columns + len_col;
1350
1351 i = 4;
1352
1353 while (attr_tab[i].attr != NULL)
1354 {
1355 if (attr_tab[i].size != 0)
1356 {
1357 if (attr_tab[i].val > 40 && attr_tab[i].val < 47)
1358 {
1359 /* remove the 'T' between date and time
1360 */
1361 p = (char *)(db_entry)+attr_tab[i].off;
1362 p = strchr(p, 'T');
1363 if (p) *p = ' ';
1364 }
1365 p = end;
1366 end = null_or_val(end,((char *)(db_entry)+attr_tab[i].off),&size,1);
1367 if (p != end)
1368 {
1369 if ((attr_tab[i].val != SH_SLOT_HOST) &&
1370 (attr_tab[i].val != SH_SLOT_GROUP))
1371 {
1372 c_end = null_or_val (c_end, attr_tab[i].attr, &c_size,0);
1373 }
1374 else
1375 {
1376 /*
1377 * 'host' is a reserved word in SQL
1378 */
1379 if (attr_tab[i].val == SH_SLOT_HOST)
1380 c_end = null_or_val (c_end, _("fromhost"), &c_size,0);
1381 /*
1382 * 'group' is a reserved word in SQL
1383 */
1384 else /* if (attr_tab[i].val == SH_SLOT_GROUP) */
1385 c_end = null_or_val (c_end, _("grp"), &c_size,0);
1386 }
1387 }
1388 /*@-type@*//* byte* versus char[..] */
1389 if (attr_tab[i].inHash == 1 &&
1390 ((char *)(db_entry)+attr_tab[i].off) != '\0')
1391 {
1392 (void)md5Update(&crc,
1393 (sh_byte*) ((char *)(db_entry)+attr_tab[i].off),
1394 (int)strlen((char *)(db_entry)+attr_tab[i].off));
1395 }
1396 /*@+type@*/
1397 }
1398 else if (attr_tab[i].val >= START_SEC_LONGS &&
1399 attr_tab[i].val <= END_SEC_LONGS)
1400 {
1401 (void)
1402 sl_snprintf(end, (size_t)(size-1), _(",\'%lu\'"),
1403 db_entry->ulong_data[attr_tab[i].val-START_SEC_LONGS]);
1404 while (*end != '\0') { ++end; --size; }
1405 (void) sl_snprintf(c_end, (size_t)(c_size-1),
1406 _(",%s"), attr_tab[i].attr);
1407 while (*c_end != '\0') { ++c_end; --c_size; }
1408 if (attr_tab[i].inHash == 1)
1409 {
1410 /*@-type@*//* byte* versus char[..] */
1411 (void)
1412 md5Update(&crc,
1413 (sh_byte *) db_entry->ulong_data[attr_tab[i].val-START_SEC_LONGS],
1414 sizeof(long));
1415 /*@+type@*/
1416 }
1417 }
1418
1419 ++i;
1420 }
1421
1422 (void) md5Digest(&crc, (uint32 *) md5buffer);
1423 /*@-bufferoverflowhigh -usedef@*/
1424 for (cnt = 0; cnt < 16; ++cnt)
1425 sprintf (&md5out[cnt*2], _("%02X"), /* known to fit */
1426 (unsigned int) md5buffer[cnt]);
1427 /*@+bufferoverflowhigh +usedef@*/
1428 md5out[32] = '\0';
1429
1430 (void) sl_snprintf(end, (size_t) (size-1), _(",%c%s%c"), '\'', md5out, '\'');
1431 while (*end != '\0') { ++end; --size; }
1432 (void) sl_snprintf(c_end, (size_t) (c_size-1),_(",log_hash"));
1433 while (*c_end != '\0') { ++c_end; --c_size; }
1434
1435
1436 if (size > 1) { *end = ')'; ++end; *end = '\0'; }
1437 if (c_size > 1) { *c_end = ')'; ++c_end; *c_end = '\0'; }
1438
1439 if (db_table[0] == '\0')
1440 (void) sl_strlcpy(db_table, _("log"), 64);
1441
1442 (void) sl_snprintf (query, SH_QUERY_MAX,
1443 _("INSERT INTO %s %s VALUES %s"),
1444 db_table, columns, values);
1445
1446 sh_database_query (query, &the_id);
1447
1448 /*@-usedef@*//* no, 'values' is allocated here */
1449 SH_FREE(values);
1450 /*@+usedef@*/
1451 SH_FREE(query);
1452
1453 SL_RETURN(the_id, _("sh_database_entry"));
1454}
1455
1456static int sh_database_comp_attr (const void *m1, const void *m2)
1457{
1458 const my_attr *mi1 = (const my_attr *) m1;
1459 const my_attr *mi2 = (const my_attr *) m2;
1460 return strcmp(mi1->attr, mi2->attr);
1461}
1462
1463
1464static void init_attr_table(void)
1465{
1466 static int first = S_TRUE;
1467 int i, j;
1468
1469#ifdef SH_STEALTH
1470 int k;
1471
1472 if (first == S_FALSE)
1473 return;
1474
1475 i = 0;
1476 while (attr_tab[i].attr_o != NULL)
1477 {
1478 j = strlen(attr_tab[i].attr_o);
1479 attr_tab[i].attr = malloc (j+1); /* only once */
1480 if (NULL == attr_tab[i].attr)
1481 return;
1482 for (k = 0; k < j; ++k)
1483 attr_tab[i].attr[k] = attr_tab[i].attr_o[k] ^ XOR_CODE;
1484 attr_tab[i].attr[j] = '\0';
1485 attr_tab[i].alen = strlen(attr_tab[i].attr_o);
1486 ++i;
1487 }
1488 first = S_FALSE;
1489
1490#else
1491
1492 if (first == S_FALSE)
1493 return;
1494
1495 i = 0;
1496 while (attr_tab[i].attr_o != NULL)
1497 {
1498 attr_tab[i].attr = attr_tab[i].attr_o;
1499 attr_tab[i].alen = strlen(attr_tab[i].attr_o);
1500 ++i;
1501 }
1502 first = S_FALSE;
1503
1504#endif
1505
1506 /* create a sorted table for binary search
1507 */
1508 attr_tab_srch = SH_ALLOC(i * sizeof(my_attr));
1509 for (j=0; j<i; ++j)
1510 memcpy(&attr_tab_srch[j], &attr_tab[j], sizeof(my_attr));
1511 qsort(attr_tab_srch, i, sizeof(my_attr), sh_database_comp_attr);
1512 attr_tab_srch_siz = i;
1513
1514 return;
1515}
1516
1517int sh_database_add_to_hash (const char * str)
1518{
1519 int i;
1520
1521 if (!str)
1522 return -1;
1523 init_attr_table();
1524 if (0 == strcmp(str, _("log_msg"))) { attr_tab[3].inHash = 1; return 0;}
1525 if (0 == strcmp(str, _("log_sev"))) { attr_tab[0].inHash = 1; return 0;}
1526 if (0 == strcmp(str, _("log_time"))) { attr_tab[1].inHash = 1; return 0;}
1527 if (0 == strcmp(str, _("log_host"))) { attr_tab[2].inHash = 1; return 0;}
1528 i = 4;
1529 while (attr_tab[i].attr != NULL)
1530 {
1531 if (0 == strcmp(str, attr_tab[i].attr))
1532 { attr_tab[i].inHash = 1; return 0; }
1533 ++i;
1534 }
1535 return -1;
1536}
1537
1538static int is_escaped(char * p_in) {
1539
1540 int escp = 0;
1541 int retv = S_TRUE;
1542 unsigned char * p = (unsigned char *) p_in;
1543
1544 if (*p != '\0')
1545 {
1546 do
1547 {
1548 if (*p <= 126 && *p >= 32)
1549 {
1550 if (escp == 0)
1551 {
1552 if (!((*p == '\'') || (*p == '\"') || (*p == '\\')))
1553 /* do nothing */;
1554 else if (*p == '\\')
1555 {
1556#ifndef WITH_MYSQL
1557 if (p[1] == '\'')
1558 {
1559 *p = '\'';
1560 }
1561#endif
1562 escp = 1;
1563 }
1564 else
1565 retv = S_FALSE; /* (*p == '\'' || *p == '\"') */
1566 }
1567 else /* escp == 1 */
1568 {
1569 escp = 0;
1570 }
1571 }
1572 else /* *p > 126 || *p < 32 */
1573 {
1574 retv = S_FALSE;
1575 }
1576
1577 ++p;
1578
1579 }
1580 while (*p != '\0');
1581 }
1582
1583 if (escp == 0)
1584 return retv;
1585 else
1586 return S_FALSE;
1587}
1588
1589/* this is not a real XML parser, but it copes with the XML format of
1590 * the log messages provided by sh_error_handle()
1591 */
1592static
1593char * sh_database_parse (char * message, dbins * db_entry)
1594{
1595 static int first = S_TRUE;
1596 char * p;
1597 char * q;
1598 char * z;
1599 dbins * new;
1600 int i;
1601 size_t j;
1602 my_attr * res;
1603 my_attr key;
1604 char key_str[64];
1605
1606 SL_ENTER(_("sh_database_parse"));
1607
1608 if (!message || *message == '\0')
1609 SL_RETURN (NULL, _("sh_database_parse"));
1610
1611 if (first == S_TRUE)
1612 {
1613 init_attr_table();
1614 first = S_FALSE;
1615 }
1616
1617 p = strchr (message, '<');
1618 if (!p)
1619 SL_RETURN (NULL, _("sh_database_parse"));
1620
1621 while ((*p != '\0') && (*p != '>'))
1622 {
1623 if (p[0] == 'l' && p[1] == 'o' && p[2] == 'g' &&
1624 (p[3] == ' ' || p[3] == '>'))
1625 {
1626 p = &p[4];
1627 goto parse;
1628 }
1629 else if (p[0] == '/' && p[1] == '>')
1630 SL_RETURN (&p[2], _("sh_database_parse"));
1631 else if (p[0] == '/' && p[1] == 'l' && p[2] == 'o' &&
1632 p[3] == 'g' && p[4] == '>')
1633 SL_RETURN (&p[5], _("sh_database_parse"));
1634 ++p;
1635 }
1636 SL_RETURN(NULL, _("sh_database_parse"));
1637
1638 parse:
1639
1640 while (*p == ' ' || *p == '>')
1641 ++p;
1642
1643 if (*p == '\0')
1644 SL_RETURN(NULL, _("sh_database_parse"));
1645
1646 if (*p != '<' && *p != '/')
1647 goto par2;
1648
1649 if (p[0] == '<' && p[1] == 'l' &&
1650 p[2] == 'o' && p[3] == 'g')
1651 {
1652 /*
1653 * recursive call
1654 */
1655 new = SH_ALLOC(sizeof(dbins));
1656 init_db_entry(new);
1657 db_entry->next = new;
1658 p = sh_database_parse (p, new);
1659 }
1660
1661 if (p[0] == '/' && p[1] == '>')
1662 SL_RETURN (&p[1], _("sh_database_parse"));
1663
1664 if (p[0] == '<' && p[1] == '/' && p[2] == 'l' &&
1665 p[3] == 'o' && p[4] == 'g' && p[5] == '>')
1666 SL_RETURN (&p[5], _("sh_database_parse"));
1667
1668 par2:
1669
1670 /* non-whitespace
1671 */
1672 for (i=0; i < 64; ++i)
1673 {
1674 if (p[i] != '=')
1675 {
1676 key_str[i] = p[i];
1677 }
1678 else
1679 {
1680 key_str[i] = '\0';
1681 break;
1682 }
1683 }
1684 key_str[63] = '\0';
1685 key.attr = &key_str[0];
1686
1687 res = bsearch(&key, attr_tab_srch, attr_tab_srch_siz,
1688 sizeof(my_attr), sh_database_comp_attr);
1689
1690 if (res != NULL)
1691 {
1692 j = res->alen; /* strlen(attr_tab[i].attr); */
1693 if (p[j] == '=' && p[j+1] == '"')
1694 {
1695 q = strchr(&p[j+2], '"');
1696 if (q)
1697 {
1698 *q = '\0';
1699
1700 if (S_TRUE == is_escaped(&p[j+2])) {
1701
1702 if (res->val == 1)
1703 (void) sl_strlcpy(db_entry->sev, &p[j+2],
1704 (size_t)res->size);
1705 else if (res->val == 2)
1706 {
1707 z = strchr(&p[j+2], 'T');
1708 if (z) *z = ' ';
1709 (void) sl_strlcpy(db_entry->time, &p[j+2], 20);
1710 }
1711 else if (res->val == 3)
1712 (void) sl_strlcpy(db_entry->host, &p[j+2],
1713 (size_t) res->size);
1714 else if (res->val == 4)
1715 (void) sl_strlcpy(db_entry->msg, &p[j+2],
1716 (size_t) res->size);
1717 else if (res->size != 0)
1718 {
1719 (void) sl_strlcpy( (((char *)(db_entry))+ res->off),
1720 &p[j+2],
1721 (size_t) res->size);
1722 }
1723 else if (res->val >= START_SEC_LONGS)
1724 {
1725 db_entry->ulong_data[res->val-START_SEC_LONGS]
1726 = strtoul(&p[j+2], (char **) NULL, 10);
1727 /* atol(&p[j+2]); */
1728 }
1729
1730 *q = '"';
1731 p = q;
1732 ++p;
1733
1734 goto parse;
1735 }
1736 else { /* S_FALSE == is_escaped(&p[j+2]) */
1737 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
1738 _("Message not properly escaped"),
1739 _("sh_database_parse"));
1740 SL_RETURN(NULL, _("sh_database_parse"));
1741 }
1742 }
1743 else /* q == NULL */
1744 {
1745 SL_RETURN(NULL, _("sh_database_parse"));
1746 }
1747 }
1748 }
1749
1750 /* unknown attribute, skip
1751 */
1752 while ((p != NULL) && (*p != '\0') && (*p != ' '))
1753 ++p;
1754
1755 goto parse;
1756}
1757
1758static int enter_wrapper = 1;
1759
1760int set_enter_wrapper (const char * str)
1761{
1762 return sh_util_flagval(str, &enter_wrapper);
1763}
1764
1765/* recursively enter linked list of messages into database, last first
1766 */
1767long sh_database_insert_rec (dbins * curr, int depth, char * host)
1768{
1769 unsigned long id = 0;
1770
1771 SL_ENTER(_("sh_database_insert_rec"));
1772
1773 if (curr->next)
1774 {
1775 /*
1776 prev = curr->next;
1777 sl_strlcpy(prev->host, curr->host, 64);
1778 id = sh_database_insert_rec (curr->next, (depth + 1));
1779 */
1780 ++depth;
1781 id = sh_database_insert_rec (curr->next, depth, curr->host);
1782 }
1783
1784 if (host)
1785 sl_strlcpy(curr->host, host, 64);
1786
1787 if (id != 0) /* this is a server wrapper */
1788 {
1789 if (enter_wrapper != 0)
1790 {
1791 id = sh_database_entry (curr, id);
1792 }
1793 }
1794 else
1795 {
1796 /*
1797 * id = -1 is the client message; log_ref will be NULL
1798 */
1799 if (depth > 0) /* this is a client message */
1800 id = sh_database_entry (curr, -1);
1801 else /* this is a generic server message */
1802 id = sh_database_entry (curr, 0);
1803 }
1804
1805 SH_FREE(curr);
1806
1807 SL_RETURN(id, _("sh_database_insert_rec"));
1808}
1809
1810int sh_database_insert (char * message)
1811{
1812 dbins * db_entry;
1813
1814 SL_ENTER(_("sh_database_insert"));
1815
1816 db_entry = SH_ALLOC(sizeof(dbins));
1817 init_db_entry(db_entry);
1818
1819 /* recursively parse the message into a linked list
1820 */
1821 (void) sh_database_parse (message, db_entry);
1822
1823 /* recursively enter the linked list into the database
1824 */
1825 (void) sh_database_insert_rec (db_entry, 0, NULL);
1826
1827 SL_RETURN(0, _("sh_database_insert"));
1828}
1829
1830#endif
Note: See TracBrowser for help on using the repository browser.