source: trunk/src/sh_database.c@ 2

Last change on this file since 2 was 1, checked in by katerina, 19 years ago

Initial import

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