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