source: trunk/src/sh_database.c@ 25

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

Minor code revisions.

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