source: trunk/src/sh_database.c @ 454

Last change on this file since 454 was 454, checked in by katerina, 7 years ago

Fix for ticket #355 (use calloc instead of malloc).

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