| 1 | #include "config_xor.h"
 | 
|---|
| 2 | 
 | 
|---|
| 3 | #ifdef USE_LOGFILE_MONITOR
 | 
|---|
| 4 | 
 | 
|---|
| 5 | #include <string.h>
 | 
|---|
| 6 | #include <ctype.h>
 | 
|---|
| 7 | 
 | 
|---|
| 8 | #undef  FIL__
 | 
|---|
| 9 | #define FIL__  _("sh_log_repeat.c")
 | 
|---|
| 10 | 
 | 
|---|
| 11 | #include "samhain.h"
 | 
|---|
| 12 | #include "sh_pthread.h"
 | 
|---|
| 13 | #include "sh_utils.h"
 | 
|---|
| 14 | #include "sh_string.h"
 | 
|---|
| 15 | #include "sh_log_check.h"
 | 
|---|
| 16 | #include "sh_log_evalrule.h"
 | 
|---|
| 17 | 
 | 
|---|
| 18 | #define SH_NHIST   12
 | 
|---|
| 19 | #define SH_NFINT    5
 | 
|---|
| 20 | #define SH_NFIELDS  5*sizeof(SINT32) /* 16 */
 | 
|---|
| 21 | #define SH_NBLOCK  63
 | 
|---|
| 22 | 
 | 
|---|
| 23 | typedef enum
 | 
|---|
| 24 | {
 | 
|---|
| 25 |   SH_GFLAG_EMAIL = 1 << 0,
 | 
|---|
| 26 |   SH_GFLAG_PATH  = 1 << 1,
 | 
|---|
| 27 |   SH_GFLAG_IP    = 1 << 2,
 | 
|---|
| 28 |   SH_GFLAG_FQDN  = 1 << 3,
 | 
|---|
| 29 |   SH_GFLAG_NUM   = 1 << 4,
 | 
|---|
| 30 |   SH_GFLAG_ELSE  = 1 << 5,
 | 
|---|
| 31 | 
 | 
|---|
| 32 |   SH_GFLAG_XNUM  = 1 << 6,
 | 
|---|
| 33 |   SH_GFLAG_CHAR  = 1 << 7,
 | 
|---|
| 34 |   SH_GFLAG_USC   = 1 << 8
 | 
|---|
| 35 | } SH_GFlags;
 | 
|---|
| 36 | 
 | 
|---|
| 37 | 
 | 
|---|
| 38 | /* 64 bytes 
 | 
|---|
| 39 |  */
 | 
|---|
| 40 | struct gestalt {
 | 
|---|
| 41 |   unsigned char hist[SH_NHIST];      /* time histogram 12 minutes   */
 | 
|---|
| 42 |   union {
 | 
|---|
| 43 |     unsigned char flags[SH_NFIELDS]; /* flags indicating field type */
 | 
|---|
| 44 |     SINT32        flint[SH_NFINT];
 | 
|---|
| 45 |   } f;
 | 
|---|
| 46 |   UINT16      sum[SH_NFIELDS];     /* checksum of field           */
 | 
|---|
| 47 |   UINT16      ltime;               /* last time, in minutes       */
 | 
|---|
| 48 |   UINT16      total;               /* seen how often?             */
 | 
|---|
| 49 | };
 | 
|---|
| 50 | 
 | 
|---|
| 51 | static unsigned int     nrec = 0;    /* size of array               */
 | 
|---|
| 52 | static unsigned int     urec = 0;    /* in use thereof              */
 | 
|---|
| 53 | static struct gestalt * arec = NULL; /* array                       */
 | 
|---|
| 54 | 
 | 
|---|
| 55 | static int      repeat_count = 24;   /* triggers report             */
 | 
|---|
| 56 | static int     clean_counter = 0;    /* cleanup after N inserts     */
 | 
|---|
| 57 | static int        free_slots = 0;    /* free slots available        */
 | 
|---|
| 58 | 
 | 
|---|
| 59 | #define SH_CLEANUP 256
 | 
|---|
| 60 | 
 | 
|---|
| 61 | static struct gestalt * add_entry (unsigned char * flags, UINT16 * sum, 
 | 
|---|
| 62 |                                    time_t ltime)
 | 
|---|
| 63 | {
 | 
|---|
| 64 |   struct gestalt * array = NULL;
 | 
|---|
| 65 | 
 | 
|---|
| 66 |  start:
 | 
|---|
| 67 |   if (urec < nrec)
 | 
|---|
| 68 |     {
 | 
|---|
| 69 |       if (free_slots)
 | 
|---|
| 70 |         {
 | 
|---|
| 71 |           unsigned int i;
 | 
|---|
| 72 |           for (i = 0; i < urec; ++i)
 | 
|---|
| 73 |             {
 | 
|---|
| 74 |               if (arec[i].total == 0)
 | 
|---|
| 75 |                 {
 | 
|---|
| 76 |                   array = &arec[i];
 | 
|---|
| 77 |                   --free_slots;
 | 
|---|
| 78 |                   break;
 | 
|---|
| 79 |                 }
 | 
|---|
| 80 |             }
 | 
|---|
| 81 |         }
 | 
|---|
| 82 | 
 | 
|---|
| 83 |       if (!array)
 | 
|---|
| 84 |         {
 | 
|---|
| 85 |           array = &arec[urec];
 | 
|---|
| 86 |           ++urec;
 | 
|---|
| 87 |         }
 | 
|---|
| 88 | 
 | 
|---|
| 89 |       memcpy(array->sum,       sum, sizeof(UINT16)      * SH_NFIELDS);
 | 
|---|
| 90 |       memcpy(array->f.flags, flags, sizeof(unsigned char) * SH_NFIELDS);
 | 
|---|
| 91 |       memset(array->hist,        0, sizeof(unsigned char) * SH_NHIST);
 | 
|---|
| 92 | 
 | 
|---|
| 93 |       array->ltime               = (UINT16)(ltime % 60);
 | 
|---|
| 94 |       array->hist[SH_NHIST-1]    = 1;
 | 
|---|
| 95 |       array->total               = 1;
 | 
|---|
| 96 | 
 | 
|---|
| 97 |       ++clean_counter;
 | 
|---|
| 98 |       return array;
 | 
|---|
| 99 |     }
 | 
|---|
| 100 | 
 | 
|---|
| 101 |   array =    SH_ALLOC(sizeof(struct gestalt) * (nrec + SH_NBLOCK + 1));
 | 
|---|
| 102 |   memset(array,    0, sizeof(struct gestalt) * (nrec + SH_NBLOCK + 1));
 | 
|---|
| 103 |   memcpy(array, arec, sizeof(struct gestalt) * (nrec));
 | 
|---|
| 104 | 
 | 
|---|
| 105 |   nrec += (SH_NBLOCK + 1);
 | 
|---|
| 106 |   goto start;
 | 
|---|
| 107 | }
 | 
|---|
| 108 | 
 | 
|---|
| 109 | static UINT16 shift_history(unsigned char * hist, unsigned int shift, 
 | 
|---|
| 110 |                               UINT16 total)
 | 
|---|
| 111 | {
 | 
|---|
| 112 |   unsigned int i, j = 0;
 | 
|---|
| 113 | 
 | 
|---|
| 114 |   if (shift >= SH_NHIST)
 | 
|---|
| 115 |     {
 | 
|---|
| 116 |       memset(hist,      0, sizeof(unsigned char) * SH_NHIST);
 | 
|---|
| 117 |       return 0;
 | 
|---|
| 118 |     }
 | 
|---|
| 119 | 
 | 
|---|
| 120 |   for (i = shift; i < SH_NHIST; ++i)
 | 
|---|
| 121 |     {
 | 
|---|
| 122 |       if (j < shift)
 | 
|---|
| 123 |         total  -= hist[j];
 | 
|---|
| 124 |       hist[j] = hist[i];
 | 
|---|
| 125 |       ++j;
 | 
|---|
| 126 |     }
 | 
|---|
| 127 |   for (i = (SH_NHIST-shift); i < SH_NHIST; ++i)
 | 
|---|
| 128 |     {
 | 
|---|
| 129 |       hist[i] = 0;
 | 
|---|
| 130 |     }
 | 
|---|
| 131 |   return total;
 | 
|---|
| 132 | }
 | 
|---|
| 133 |  
 | 
|---|
| 134 | static void update_entry (struct gestalt * array, time_t ltime)
 | 
|---|
| 135 | {
 | 
|---|
| 136 |   UINT16 ntime = (UINT16)(ltime % 60);
 | 
|---|
| 137 | 
 | 
|---|
| 138 |   if (array->ltime == ntime)
 | 
|---|
| 139 |     {
 | 
|---|
| 140 |       if (array->hist[SH_NHIST-1] < 255) 
 | 
|---|
| 141 |         {
 | 
|---|
| 142 |           ++(array->hist[SH_NHIST-1]);
 | 
|---|
| 143 |           ++(array->total);
 | 
|---|
| 144 |         }
 | 
|---|
| 145 |     }
 | 
|---|
| 146 |   else if (array->ltime < ntime)
 | 
|---|
| 147 |     {
 | 
|---|
| 148 |       unsigned int shift = ntime - array->ltime;
 | 
|---|
| 149 |       array->total = shift_history(array->hist, shift, array->total);
 | 
|---|
| 150 |       array->hist[SH_NHIST-1] = 1;
 | 
|---|
| 151 |       array->ltime = ntime;
 | 
|---|
| 152 |       ++(array->total);
 | 
|---|
| 153 |     }
 | 
|---|
| 154 | }
 | 
|---|
| 155 | 
 | 
|---|
| 156 | static struct gestalt * update_or_add (unsigned char * flags, UINT16 * sum, 
 | 
|---|
| 157 |                                        time_t ltime)
 | 
|---|
| 158 | {
 | 
|---|
| 159 |   SINT32 flint[SH_NFINT];
 | 
|---|
| 160 |  start:
 | 
|---|
| 161 | 
 | 
|---|
| 162 |   if (arec)
 | 
|---|
| 163 |     {
 | 
|---|
| 164 |       unsigned int i;
 | 
|---|
| 165 |       struct gestalt * array = arec;
 | 
|---|
| 166 | 
 | 
|---|
| 167 |       memcpy(flint, flags, SH_NFIELDS);
 | 
|---|
| 168 | 
 | 
|---|
| 169 |       for (i = 0; i < urec; ++i)
 | 
|---|
| 170 |         {
 | 
|---|
| 171 |           /* Check whether field types match. Integer
 | 
|---|
| 172 |            * comparison is much faster than memcmp() [tested].
 | 
|---|
| 173 |            */
 | 
|---|
| 174 |           if (flint[0] == array->f.flint[0] &&
 | 
|---|
| 175 |               flint[1] == array->f.flint[1] &&
 | 
|---|
| 176 |               flint[2] == array->f.flint[2] &&
 | 
|---|
| 177 |               flint[3] == array->f.flint[3] &&
 | 
|---|
| 178 |               flint[4] == array->f.flint[4])
 | 
|---|
| 179 |             {
 | 
|---|
| 180 |               unsigned int j; 
 | 
|---|
| 181 |               int c1 = 0, c2 = 0;
 | 
|---|
| 182 |               UINT16 * asum = array->sum;
 | 
|---|
| 183 | 
 | 
|---|
| 184 |               for (j = 0; j < SH_NFIELDS; ++j)
 | 
|---|
| 185 |                 {
 | 
|---|
| 186 |                   if (flags[j] == SH_GFLAG_ELSE)
 | 
|---|
| 187 |                     {
 | 
|---|
| 188 |                       ++c1;
 | 
|---|
| 189 |                       if (asum[j] == sum[j]) 
 | 
|---|
| 190 |                         ++c2;
 | 
|---|
| 191 |                     }
 | 
|---|
| 192 |                 }
 | 
|---|
| 193 | 
 | 
|---|
| 194 |               if (c1 == c2)
 | 
|---|
| 195 |                 {
 | 
|---|
| 196 |                   /* Found a matching entry, update time histogram
 | 
|---|
| 197 |                    */
 | 
|---|
| 198 |                   update_entry (array, ltime);
 | 
|---|
| 199 |                   return array;
 | 
|---|
| 200 |                 }
 | 
|---|
| 201 |             }
 | 
|---|
| 202 |           ++array;
 | 
|---|
| 203 |         }
 | 
|---|
| 204 | 
 | 
|---|
| 205 |       /* No match found, create a new entry
 | 
|---|
| 206 |        */
 | 
|---|
| 207 |       array = add_entry (flags, sum, ltime);
 | 
|---|
| 208 |       return array;
 | 
|---|
| 209 |     }
 | 
|---|
| 210 |   
 | 
|---|
| 211 |   arec = SH_ALLOC(sizeof(struct gestalt) * SH_NBLOCK);
 | 
|---|
| 212 |   nrec = SH_NBLOCK;
 | 
|---|
| 213 |   urec = 0;
 | 
|---|
| 214 | 
 | 
|---|
| 215 |   goto start;
 | 
|---|
| 216 | }
 | 
|---|
| 217 | 
 | 
|---|
| 218 | /* --------------------------------------------------------------------
 | 
|---|
| 219 |  *
 | 
|---|
| 220 |  * crc16 checksum from the linux kernel.
 | 
|---|
| 221 |  * This source code is licensed under the GNU General Public License,
 | 
|---|
| 222 |  * Version 2. 
 | 
|---|
| 223 |  */
 | 
|---|
| 224 | 
 | 
|---|
| 225 | /** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
 | 
|---|
| 226 | UINT16 const crc16_table[256] = {
 | 
|---|
| 227 |   0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
 | 
|---|
| 228 |   0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
 | 
|---|
| 229 |   0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
 | 
|---|
| 230 |   0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
 | 
|---|
| 231 |   0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
 | 
|---|
| 232 |   0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
 | 
|---|
| 233 |   0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
 | 
|---|
| 234 |   0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
 | 
|---|
| 235 |   0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
 | 
|---|
| 236 |   0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
 | 
|---|
| 237 |   0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
 | 
|---|
| 238 |   0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
 | 
|---|
| 239 |   0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
 | 
|---|
| 240 |   0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
 | 
|---|
| 241 |   0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
 | 
|---|
| 242 |   0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
 | 
|---|
| 243 |   0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
 | 
|---|
| 244 |   0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
 | 
|---|
| 245 |   0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
 | 
|---|
| 246 |   0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
 | 
|---|
| 247 |   0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
 | 
|---|
| 248 |   0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
 | 
|---|
| 249 |   0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
 | 
|---|
| 250 |   0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
 | 
|---|
| 251 |   0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
 | 
|---|
| 252 |   0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
 | 
|---|
| 253 |   0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
 | 
|---|
| 254 |   0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
 | 
|---|
| 255 |   0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
 | 
|---|
| 256 |   0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
 | 
|---|
| 257 |   0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
 | 
|---|
| 258 |   0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
 | 
|---|
| 259 | };
 | 
|---|
| 260 | 
 | 
|---|
| 261 | static inline UINT16 crc16_byte(UINT16 crc, const unsigned char data)
 | 
|---|
| 262 | {
 | 
|---|
| 263 |   return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
 | 
|---|
| 264 | }
 | 
|---|
| 265 | 
 | 
|---|
| 266 | /**
 | 
|---|
| 267 |  * crc16 - compute the CRC-16 for the data buffer
 | 
|---|
| 268 |  * @crc:        previous CRC value
 | 
|---|
| 269 |  * @buffer:     data pointer
 | 
|---|
| 270 |  * @len:        number of bytes in the buffer
 | 
|---|
| 271 |  *
 | 
|---|
| 272 |  * Returns the updated CRC value.
 | 
|---|
| 273 |  */
 | 
|---|
| 274 | static inline UINT16 crc16(UINT16 crc, const unsigned char * buffer, 
 | 
|---|
| 275 |                              size_t len)
 | 
|---|
| 276 | {
 | 
|---|
| 277 |   while (len--)
 | 
|---|
| 278 |     crc = crc16_byte(crc, *buffer++);
 | 
|---|
| 279 |   return crc;
 | 
|---|
| 280 | }
 | 
|---|
| 281 | 
 | 
|---|
| 282 | 
 | 
|---|
| 283 | /* end crc16 code
 | 
|---|
| 284 |  *
 | 
|---|
| 285 |  * -------------------------------------------------------------------- */
 | 
|---|
| 286 | 
 | 
|---|
| 287 | static void  classify(char ** splits, size_t * lengths, unsigned int nfields, 
 | 
|---|
| 288 |                       unsigned char * flags, UINT16 * sums)
 | 
|---|
| 289 | {
 | 
|---|
| 290 |   unsigned int i;
 | 
|---|
| 291 |   unsigned int flag;
 | 
|---|
| 292 | 
 | 
|---|
| 293 |   /* flags we don't want to see in XYZ 
 | 
|---|
| 294 |    */
 | 
|---|
| 295 |   static int m_ip    = SH_GFLAG_PATH|SH_GFLAG_EMAIL|SH_GFLAG_USC|SH_GFLAG_ELSE|SH_GFLAG_CHAR|SH_GFLAG_XNUM;
 | 
|---|
| 296 |   static int m_num   = SH_GFLAG_PATH|SH_GFLAG_EMAIL|SH_GFLAG_USC|SH_GFLAG_ELSE|SH_GFLAG_CHAR;
 | 
|---|
| 297 |   static int m_fqdn  = SH_GFLAG_PATH|SH_GFLAG_EMAIL|SH_GFLAG_USC|SH_GFLAG_ELSE;
 | 
|---|
| 298 |   static int m_email = SH_GFLAG_PATH;
 | 
|---|
| 299 | 
 | 
|---|
| 300 |   nfields = (nfields > SH_NFIELDS) ? SH_NFIELDS : nfields;
 | 
|---|
| 301 | 
 | 
|---|
| 302 |   for (i = 0; i < nfields; ++i) 
 | 
|---|
| 303 |     {
 | 
|---|
| 304 |       char *p = splits[i];
 | 
|---|
| 305 |       unsigned int np   = 0;
 | 
|---|
| 306 |       unsigned int fqdn = 0;
 | 
|---|
| 307 | 
 | 
|---|
| 308 |       flag = 0;
 | 
|---|
| 309 | 
 | 
|---|
| 310 |       while (*p)
 | 
|---|
| 311 |         {
 | 
|---|
| 312 |           if (isxdigit((unsigned int)*p))
 | 
|---|
| 313 |             {
 | 
|---|
| 314 |               if (isdigit((unsigned int)*p))
 | 
|---|
| 315 |                 {
 | 
|---|
| 316 |                   flag |= SH_GFLAG_NUM;
 | 
|---|
| 317 |                 }
 | 
|---|
| 318 |               else
 | 
|---|
| 319 |                 {
 | 
|---|
| 320 |                   flag |= SH_GFLAG_XNUM;
 | 
|---|
| 321 |                 }
 | 
|---|
| 322 |             }
 | 
|---|
| 323 |           else if (*p == '.')
 | 
|---|
| 324 |             {
 | 
|---|
| 325 |               flag |= SH_GFLAG_IP;
 | 
|---|
| 326 |               ++np;
 | 
|---|
| 327 |             }
 | 
|---|
| 328 |           else if (*p == '/')
 | 
|---|
| 329 |             {
 | 
|---|
| 330 |               flag |= SH_GFLAG_PATH;
 | 
|---|
| 331 |             }
 | 
|---|
| 332 |           else if (*p == '@')
 | 
|---|
| 333 |             {
 | 
|---|
| 334 |               flag |= SH_GFLAG_EMAIL;
 | 
|---|
| 335 |             }
 | 
|---|
| 336 |           else if (*p == '-')
 | 
|---|
| 337 |             {
 | 
|---|
| 338 |               flag |= SH_GFLAG_FQDN;
 | 
|---|
| 339 |             }
 | 
|---|
| 340 |           else if (*p == '_')
 | 
|---|
| 341 |             {
 | 
|---|
| 342 |               flag |= SH_GFLAG_USC;
 | 
|---|
| 343 |             }
 | 
|---|
| 344 |           else if (isalpha((unsigned int)*p))
 | 
|---|
| 345 |             {
 | 
|---|
| 346 |               if (flag & SH_GFLAG_IP)
 | 
|---|
| 347 |                 ++fqdn;
 | 
|---|
| 348 |               flag |= SH_GFLAG_CHAR;
 | 
|---|
| 349 |             }
 | 
|---|
| 350 |           else if (!isascii((unsigned int)*p))
 | 
|---|
| 351 |             {
 | 
|---|
| 352 |               flags[i] = SH_GFLAG_ELSE;
 | 
|---|
| 353 |               break;
 | 
|---|
| 354 |             }
 | 
|---|
| 355 |           else
 | 
|---|
| 356 |             {
 | 
|---|
| 357 |               flag |= SH_GFLAG_ELSE;
 | 
|---|
| 358 |             }
 | 
|---|
| 359 |           ++p;
 | 
|---|
| 360 |         }
 | 
|---|
| 361 | 
 | 
|---|
| 362 |       if (flags[i] == 0)
 | 
|---|
| 363 |         {
 | 
|---|
| 364 |           if (0 == (flag & m_ip)         && 
 | 
|---|
| 365 |               0 != (flag & SH_GFLAG_IP)  && 
 | 
|---|
| 366 |               0 != (flag & SH_GFLAG_NUM) && 
 | 
|---|
| 367 |               np > 2)
 | 
|---|
| 368 |             {
 | 
|---|
| 369 |               flags[i] = SH_GFLAG_IP;
 | 
|---|
| 370 |             }
 | 
|---|
| 371 |           else if (0 == (flag & m_num) && 
 | 
|---|
| 372 |                    (0 != (flag & SH_GFLAG_NUM) || 0 != (flag & SH_GFLAG_XNUM)))
 | 
|---|
| 373 |             {
 | 
|---|
| 374 |               flags[i] = SH_GFLAG_NUM;
 | 
|---|
| 375 |             }
 | 
|---|
| 376 |           else if (0 == (flag & m_fqdn)        && 
 | 
|---|
| 377 |                    0 != (flag & SH_GFLAG_IP)   && 
 | 
|---|
| 378 |                    0 != (flag & SH_GFLAG_CHAR) && 
 | 
|---|
| 379 |                    fqdn)
 | 
|---|
| 380 |             {
 | 
|---|
| 381 |               flags[i] = SH_GFLAG_FQDN;
 | 
|---|
| 382 |             }
 | 
|---|
| 383 |           else if ('/' == splits[i][0])
 | 
|---|
| 384 |             {
 | 
|---|
| 385 |               flags[i] = SH_GFLAG_PATH;
 | 
|---|
| 386 |             }
 | 
|---|
| 387 |           else if (0 == (flag & m_email)        && 
 | 
|---|
| 388 |                    0 != (flag & SH_GFLAG_EMAIL) && 
 | 
|---|
| 389 |                    0 != (flag & SH_GFLAG_CHAR)) 
 | 
|---|
| 390 |             {
 | 
|---|
| 391 |               flags[i] = SH_GFLAG_EMAIL;
 | 
|---|
| 392 |             }
 | 
|---|
| 393 |           else 
 | 
|---|
| 394 |             {
 | 
|---|
| 395 |               flags[i] = SH_GFLAG_ELSE;
 | 
|---|
| 396 |             }
 | 
|---|
| 397 |         }
 | 
|---|
| 398 | 
 | 
|---|
| 399 |       /* CRC-16 checksum
 | 
|---|
| 400 |        */ 
 | 
|---|
| 401 |       sums[i] = crc16(0, (unsigned char *) splits[i], lengths[i]);
 | 
|---|
| 402 |     }
 | 
|---|
| 403 | 
 | 
|---|
| 404 |   return;
 | 
|---|
| 405 | }
 | 
|---|
| 406 | 
 | 
|---|
| 407 | static void cleanup_array (time_t ltime)
 | 
|---|
| 408 | {
 | 
|---|
| 409 |   UINT16 ntime = (UINT16)(ltime % 60);
 | 
|---|
| 410 | 
 | 
|---|
| 411 |   if (ntime > 12) ntime -= 12;
 | 
|---|
| 412 | 
 | 
|---|
| 413 |   if (arec && urec > 0)
 | 
|---|
| 414 |     {
 | 
|---|
| 415 |       struct gestalt * array;
 | 
|---|
| 416 |       unsigned int i, last, urec_orig = urec;
 | 
|---|
| 417 | 
 | 
|---|
| 418 |       last = urec-1;
 | 
|---|
| 419 |       array = &arec[0];
 | 
|---|
| 420 |   
 | 
|---|
| 421 |       for (i = 0; i < urec_orig; ++i)
 | 
|---|
| 422 |         {
 | 
|---|
| 423 |           if (array->ltime < ntime)
 | 
|---|
| 424 |             {
 | 
|---|
| 425 |               memset(array,    0, sizeof(struct gestalt));
 | 
|---|
| 426 |               if (i != last)
 | 
|---|
| 427 |                 ++free_slots;
 | 
|---|
| 428 |               else
 | 
|---|
| 429 |                 --urec;
 | 
|---|
| 430 |             }
 | 
|---|
| 431 |         }
 | 
|---|
| 432 |       ++array;
 | 
|---|
| 433 |     }
 | 
|---|
| 434 |   clean_counter = 0;
 | 
|---|
| 435 |   return;
 | 
|---|
| 436 | }
 | 
|---|
| 437 | 
 | 
|---|
| 438 | /* ----------------------------------------------------------------------
 | 
|---|
| 439 |  *
 | 
|---|
| 440 |  *   Public functions
 | 
|---|
| 441 |  */
 | 
|---|
| 442 | 
 | 
|---|
| 443 | int sh_repeat_set_trigger (const char * str)
 | 
|---|
| 444 | {
 | 
|---|
| 445 |   unsigned long  value;
 | 
|---|
| 446 |   char * foo;
 | 
|---|
| 447 | 
 | 
|---|
| 448 |   value = (size_t) strtoul(str, &foo, 0);
 | 
|---|
| 449 | 
 | 
|---|
| 450 |   if (*foo == '\0' && value < 65535) {
 | 
|---|
| 451 |     repeat_count = value;
 | 
|---|
| 452 |     return 0;
 | 
|---|
| 453 |   }
 | 
|---|
| 454 |   return -1;
 | 
|---|
| 455 | }
 | 
|---|
| 456 | 
 | 
|---|
| 457 | static char * sh_repeat_queue = NULL;
 | 
|---|
| 458 | 
 | 
|---|
| 459 | int sh_repeat_set_queue (const char * str)
 | 
|---|
| 460 | {
 | 
|---|
| 461 |   if (!str)
 | 
|---|
| 462 |     return -1;
 | 
|---|
| 463 |   if (sh_repeat_queue)
 | 
|---|
| 464 |     SH_FREE(sh_repeat_queue);
 | 
|---|
| 465 |   sh_repeat_queue = sh_util_strdup(str);
 | 
|---|
| 466 |   return 0;
 | 
|---|
| 467 | }
 | 
|---|
| 468 | 
 | 
|---|
| 469 | static int sh_repeat_cron = S_FALSE;
 | 
|---|
| 470 | 
 | 
|---|
| 471 | int sh_repeat_set_cron (const char * str)
 | 
|---|
| 472 | {
 | 
|---|
| 473 |   return sh_util_flagval(str, &sh_repeat_cron);
 | 
|---|
| 474 | }
 | 
|---|
| 475 | 
 | 
|---|
| 476 | int sh_repeat_message_check (const sh_string * host, 
 | 
|---|
| 477 |                              const sh_string * msg, 
 | 
|---|
| 478 |                              time_t ltime)
 | 
|---|
| 479 | {
 | 
|---|
| 480 |   struct gestalt * array;
 | 
|---|
| 481 | 
 | 
|---|
| 482 |   UINT16         sums[SH_NFIELDS] = { 0 };
 | 
|---|
| 483 |   unsigned char flags[SH_NFIELDS] = { 0 };
 | 
|---|
| 484 | 
 | 
|---|
| 485 |   /* split message into SH_NFIELDS+1, discard last  */
 | 
|---|
| 486 | 
 | 
|---|
| 487 |   unsigned int nfields = SH_NFIELDS+1;
 | 
|---|
| 488 |   size_t       lengths[SH_NFIELDS+1];
 | 
|---|
| 489 |   char *       new;
 | 
|---|
| 490 |   char **      splits;
 | 
|---|
| 491 | 
 | 
|---|
| 492 |   if (repeat_count == 0)
 | 
|---|
| 493 |     return 0;
 | 
|---|
| 494 | 
 | 
|---|
| 495 |   if (sh_repeat_cron == S_FALSE)
 | 
|---|
| 496 |     {
 | 
|---|
| 497 |       char * s = sh_string_str(msg);
 | 
|---|
| 498 | 
 | 
|---|
| 499 |       if (0 == strcmp(s, _("cron")) || 0 == strcmp(s, _("CRON")))
 | 
|---|
| 500 |         return 0;
 | 
|---|
| 501 |     }
 | 
|---|
| 502 | 
 | 
|---|
| 503 |   new = sh_util_strdup_l(sh_string_str(msg), sh_string_len(msg));
 | 
|---|
| 504 | 
 | 
|---|
| 505 |   splits = split_array_token (new, &nfields, lengths, 
 | 
|---|
| 506 |                               " :,()='[]<>\t\n");
 | 
|---|
| 507 | 
 | 
|---|
| 508 |   /* classify fields                                */
 | 
|---|
| 509 | 
 | 
|---|
| 510 |   classify (splits, lengths, nfields, flags, sums); 
 | 
|---|
| 511 | 
 | 
|---|
| 512 |   /* compare                                        */
 | 
|---|
| 513 | 
 | 
|---|
| 514 |   array = update_or_add (flags, sums, ltime);
 | 
|---|
| 515 | 
 | 
|---|
| 516 |   /* report                                         */
 | 
|---|
| 517 | 
 | 
|---|
| 518 |   if (array->total > repeat_count)
 | 
|---|
| 519 |     {
 | 
|---|
| 520 |       volatile int repeat = array->total;
 | 
|---|
| 521 |       char * tmpmsg;
 | 
|---|
| 522 |       char * tmphost;
 | 
|---|
| 523 |       sh_string * alias;
 | 
|---|
| 524 | 
 | 
|---|
| 525 |       /* issue report             */
 | 
|---|
| 526 | 
 | 
|---|
| 527 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| 528 |       tmphost = sh_util_safe_name (sh_string_str(host));
 | 
|---|
| 529 |       tmpmsg  = sh_util_safe_name_keepspace (sh_string_str(msg));
 | 
|---|
| 530 |       sh_error_handle (sh_log_lookup_severity(sh_repeat_queue), 
 | 
|---|
| 531 |                        FIL__, __LINE__, 0, MSG_LOGMON_BURST, 
 | 
|---|
| 532 |                        repeat, tmpmsg, tmphost);
 | 
|---|
| 533 |       alias = sh_log_lookup_alias(sh_repeat_queue);
 | 
|---|
| 534 |       if (alias)
 | 
|---|
| 535 |         {
 | 
|---|
| 536 |           sh_error_mail (sh_string_str(alias), 
 | 
|---|
| 537 |                          sh_log_lookup_severity(sh_repeat_queue), 
 | 
|---|
| 538 |                          FIL__, __LINE__, 0, MSG_LOGMON_BURST, 
 | 
|---|
| 539 |                          repeat, tmpmsg, tmphost);
 | 
|---|
| 540 |         }
 | 
|---|
| 541 |       SH_FREE(tmpmsg);
 | 
|---|
| 542 |       SH_FREE(tmphost);
 | 
|---|
| 543 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| 544 | 
 | 
|---|
| 545 |       /* mark slot as free        */
 | 
|---|
| 546 | 
 | 
|---|
| 547 |       memset(array,    0, sizeof(struct gestalt));
 | 
|---|
| 548 |       if (array != &arec[urec-1])
 | 
|---|
| 549 |         ++free_slots;
 | 
|---|
| 550 |       else
 | 
|---|
| 551 |         urec -= 1;
 | 
|---|
| 552 |     }
 | 
|---|
| 553 | 
 | 
|---|
| 554 |   SH_FREE(new);
 | 
|---|
| 555 | 
 | 
|---|
| 556 |   /* run cleanup routine                            */
 | 
|---|
| 557 | 
 | 
|---|
| 558 |   if (clean_counter >= SH_CLEANUP)
 | 
|---|
| 559 |     {
 | 
|---|
| 560 |       cleanup_array(ltime);
 | 
|---|
| 561 |     }
 | 
|---|
| 562 | 
 | 
|---|
| 563 |   return 0;
 | 
|---|
| 564 | }
 | 
|---|
| 565 | 
 | 
|---|
| 566 | #endif
 | 
|---|