source: trunk/src/sh_database.c@ 20

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

Optimized version of tiger algorithm, and basic ingredients for unit testing (part 2)

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