source: trunk/src/sh_database.c@ 4

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

More fixes for update function, released 2.1.1 version.

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