source: trunk/src/sh_database.c@ 11

Last change on this file since 11 was 11, checked in by rainer, 19 years ago

Minor optimisations for server

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