Imported Upstream version 2.7
[ossec-hids.git] / src / analysisd / cleanevent.c
1 /* @(#) $Id: ./src/analysisd/cleanevent.c, 2011/09/08 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 Trend Micro Inc.
5  * All rights reserved.
6  *
7  * This program is a free software; you can redistribute it
8  * and/or modify it under the terms of the GNU General Public
9  * License (version 2) as published by the FSF - Free Software
10  * Foundation.
11  *
12  * License details at the LICENSE file included with OSSEC or
13  * online at: http://www.ossec.net/en/licensing.html
14  */
15
16
17 #include "shared.h"
18 #include "os_regex/os_regex.h"
19
20
21 /* local headers */
22 #include "eventinfo.h"
23 #include "analysisd.h"
24 #include "fts.h"
25 #include "config.h"
26
27
28 /* To translante between month (int) to month (char) */
29 char *(month[])={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug",
30                      "Sep","Oct","Nov","Dec"};
31
32
33
34
35 /* OS_CleanMSG v0.3: 2006/03/04
36  * Format a received message in the
37  * Eventinfo structure.
38  */
39 int OS_CleanMSG(char *msg, Eventinfo *lf)
40 {
41     int loglen;
42     char *pieces;
43     struct tm *p;
44
45     /* The message is formated in the following way:
46      * id:location:message.
47      */
48
49
50     /*  Ignoring the id of the message in here */
51     msg+=2;
52
53
54
55     /* Setting pieces as the message */
56     pieces = strchr(msg, ':');
57     if(!pieces)
58     {
59         merror(FORMAT_ERROR, ARGV0);
60         return(-1);
61     }
62
63     *pieces = '\0';
64     pieces++;
65
66
67     os_strdup(msg, lf->location);
68
69
70     /* Getting the log length */
71     loglen = strlen(pieces) + 1;
72
73
74     /* Assigning the values in the strucuture (lf->full_log) */
75     os_malloc((2*loglen) +1, lf->full_log);
76
77
78     /* Setting the whole message at full_log */
79     strncpy(lf->full_log, pieces, loglen);
80
81
82     /* Log is the one used for parsing in the decoders and rules */
83     lf->log = lf->full_log+loglen;
84     strncpy(lf->log, pieces, loglen);
85
86
87
88     /* Checking for the syslog date format.
89      * ( ex: Dec 29 10:00:01
90      *   or  2007-06-14T15:48:55-04:00 for syslog-ng isodate
91      *   or  2009-05-22T09:36:46.214994-07:00 for rsyslog )
92      */ 
93     if(
94         (
95         (loglen > 17) &&
96         (pieces[3] == ' ') &&
97         (pieces[6] == ' ') &&
98         (pieces[9] == ':') &&
99         (pieces[12] == ':') &&
100         (pieces[15] == ' ') && (lf->log+=16)
101         )
102         ||
103         (
104         (loglen > 33) &&
105         (pieces[4] == '-') &&
106         (pieces[7] == '-') &&
107         (pieces[10] == 'T') &&
108         (pieces[13] == ':') &&
109         (pieces[16] == ':') &&
110
111         (
112          ((pieces[22] == ':') &&
113           (pieces[25] == ' ') && (lf->log+=26)) ||
114
115          ((pieces[19] == '.') &&
116           (pieces[29] == ':') && (lf->log+=32))
117         )
118
119         )
120       )
121     {
122         /* Checking for an extra space in here */
123         if(*lf->log == ' ')
124             lf->log++;
125
126
127         /* Hostname */
128         pieces = lf->hostname = lf->log;
129
130
131         /* Checking for a valid hostname */
132         while(isValidChar(*pieces) == 1)
133         {
134             pieces++;
135         }
136
137
138         /* Checking if it is a syslog without hostname (common on Solaris. */
139         if(*pieces == ':' && pieces[1] == ' ')
140         {
141             /* Getting solaris 8/9 messages without hostname.
142              * In these cases, the process_name should be there.
143              * http://www.ossec.net/wiki/index.php/Log_Samples_Solaris
144              */
145             lf->program_name = lf->hostname;
146             lf->hostname = NULL;
147
148             /* Ending the program name string. */
149             *pieces = '\0';
150
151             pieces+=2;
152             lf->log = pieces;
153         }
154
155
156         /* Extracting the hostname */
157         else if(*pieces != ' ')
158         {
159             /* Invalid hostname */
160             lf->hostname = NULL;
161             pieces = NULL;
162         }
163         else
164         {
165             /* Ending the hostname string */
166             *pieces = '\0';
167
168
169             /* Moving pieces to the beginning of the log message */
170             pieces++;
171             lf->log = pieces;
172
173
174             /* Getting program_name */
175             lf->program_name = pieces;
176
177
178             /* Extracting program_name */
179             /* Valid names:
180              * p_name:
181              * p_name[pid]:
182              * p_name[pid]: [ID xx facility.severity]
183              * auth|security:info p_name:
184              *
185              */
186             while(isValidChar(*pieces) == 1)
187             {
188                 pieces++;
189             }
190
191
192             /* Checking for the first format: p_name: */
193             if((*pieces == ':') && (pieces[1] == ' '))
194             {
195                 *pieces = '\0';
196                 pieces+=2;
197             }
198
199             /* Checking for the second format: p_name[pid]: */
200             else if((*pieces == '[') && (isdigit((int)pieces[1])))
201             {
202                 *pieces = '\0';
203                 pieces+=2;
204                 while(isdigit((int)*pieces))
205                     pieces++;
206
207                 if((*pieces == ']')&& (pieces[1] == ':')&& (pieces[2] == ' '))
208                 {
209                     pieces+=3;
210                 }
211                 /* Some systems are not terminating the program name with
212                  * the ':'. Working around this in here..
213                  */
214                 else if((*pieces == ']') && (pieces[1] == ' '))
215                 {
216                     pieces+=2;
217                 }
218                 else
219                 {
220                     /* Fixing for some weird log formats. */
221                     pieces--;
222                     while(isdigit((int)*pieces))
223                     {
224                         pieces--;
225                     }
226
227                     if(*pieces == '\0')
228                         *pieces = '[';
229                     pieces = NULL;
230                     lf->program_name = NULL;
231                 }
232             }
233             /* AIX syslog. */
234             else if((*pieces == '|') && islower((int)pieces[1]))
235             {
236                 pieces+=2;
237
238                 /* Removing facility */
239                 while(isalnum((int)*pieces))
240                     pieces++;
241
242
243                 if(*pieces == ':')
244                 {
245                     /* Removing severity. */
246                     pieces++;
247                     while(isalnum((int)*pieces))
248                         pieces++;
249
250                     if(*pieces == ' ')
251                     {
252                         pieces++;
253                         lf->program_name = pieces;
254
255
256                         /* Getting program name again. */
257                         while(isValidChar(*pieces) == 1)
258                             pieces++;
259
260                         /* Checking for the first format: p_name: */
261                         if((*pieces == ':') && (pieces[1] == ' '))
262                         {
263                             *pieces = '\0';
264                             pieces+=2;
265                         }
266
267                         /* Checking for the second format: p_name[pid]: */
268                         else if((*pieces == '[') && (isdigit((int)pieces[1])))
269                         {
270                             *pieces = '\0';
271                             pieces+=2;
272                             while(isdigit((int)*pieces))
273                                 pieces++;
274
275                             if((*pieces == ']') && (pieces[1] == ':') &&
276                                (pieces[2] == ' '))
277                             {
278                                 pieces+=3;
279                             }
280                             else
281                             {
282                                 pieces = NULL;
283                             }
284                         }
285                     }
286                     else
287                     {
288                         pieces = NULL;
289                         lf->program_name = NULL;
290                     }
291                 }
292                 /* Invalid AIX. */
293                 else
294                 {
295                     pieces = NULL;
296                     lf->program_name = NULL;
297                 }
298             }
299             else
300             {
301                 pieces = NULL;
302                 lf->program_name = NULL;
303             }
304         }
305
306
307         /* Removing [ID xx facility.severity] */
308         if(pieces)
309         {
310             /* Setting log after program name */
311             lf->log = pieces;
312
313             if((pieces[0] == '[') &&
314                (pieces[1] == 'I') &&
315                (pieces[2] == 'D') &&
316                (pieces[3] == ' '))
317             {
318                 pieces+=4;
319
320                 /* Going after the ] */
321                 pieces = strchr(pieces, ']');
322                 if(pieces)
323                 {
324                     pieces+=2;
325                     lf->log = pieces;
326                 }
327             }
328         }
329
330         /* Getting program name size */
331         if(lf->program_name)
332         {
333             lf->p_name_size = strlen(lf->program_name);
334         }
335     }
336
337     /* xferlog date format
338      * Mon Apr 17 18:27:14 2006 1 64.160.42.130
339      */
340     else if((loglen > 28) &&
341             (pieces[3] == ' ')&&
342             (pieces[7] == ' ')&&
343             (pieces[10] == ' ')&&
344             (pieces[13] == ':')&&
345             (pieces[16] == ':')&&
346             (pieces[19] == ' ')&&
347             (pieces[24] == ' ')&&
348             (pieces[26] == ' '))
349     {
350         /* Moving log to the beginning of the message */
351         lf->log+=24;
352     }
353
354
355     /* Checking for snort date format
356      * ex: 01/28-09:13:16.240702  [**]
357      */
358     else if( (loglen > 24) &&
359              (pieces[2] == '/') &&
360              (pieces[5] == '-') &&
361              (pieces[8] == ':') &&
362              (pieces[11]== ':') &&
363              (pieces[14]== '.') &&
364              (pieces[21] == ' ') )
365     {
366         lf->log+=23;
367     }
368
369     /* Checking for apache log format */
370     /* [Fri Feb 11 18:06:35 2004] [warn] */
371     else if( (loglen > 27) &&
372              (pieces[0] == '[') &&
373              (pieces[4] == ' ') &&
374              (pieces[8] == ' ') &&
375              (pieces[11]== ' ') &&
376              (pieces[14]== ':') &&
377              (pieces[17]== ':') &&
378              (pieces[20]== ' ') &&
379              (pieces[25]== ']') )
380     {
381         lf->log+=27;
382     }
383
384     /* Checking for the osx asl log format.
385      * Examples:
386      * [Time 2006.12.28 15:53:55 UTC] [Facility auth] [Sender sshd] [PID 483] [Message error: PAM: Authentication failure for username from 192.168.0.2] [Level 3] [UID -2] [GID -2] [Host Hostname]
387      * [Time 2006.11.02 14:02:11 UTC] [Facility auth] [Sender sshd] [PID 856]
388      [Message refused connect from 59.124.44.34] [Level 4] [UID -2] [GID -2]
389      [Host robert-wyatts-emac]
390      */
391     else if((loglen > 26) &&
392             (pieces[0] == '[')  &&
393             (pieces[1] == 'T')  &&
394             (pieces[5] == ' ')  &&
395             (pieces[10] == '.') &&
396             (pieces[13] == '.') &&
397             (pieces[16] == ' ') &&
398             (pieces[19] == ':'))
399     {
400         /* Do not read more than 1 message entry -> log tampering */
401         short unsigned int done_message = 0;
402
403
404         /* Removing the date */
405         lf->log+=25;
406
407         /* Getting the desired values */
408         pieces = strchr(lf->log, '[');
409         while(pieces)
410         {
411             pieces++;
412
413             /* Getting the sender (set to program name) */
414             if((strncmp(pieces, "Sender ", 7) == 0) &&
415                (lf->program_name == NULL))
416             {
417                 pieces+=7;
418                 lf->program_name = pieces;
419
420                 /* Getting the closing brackets */
421                 pieces = strchr(pieces, ']');
422                 if(pieces)
423                 {
424                     *pieces = '\0';
425
426                     /* Setting program_name size */
427                     lf->p_name_size = strlen(lf->program_name);
428
429                     pieces++;
430                 }
431                 /* Invalid program name */
432                 else
433                 {
434                     lf->program_name = NULL;
435                     break;
436                 }
437             }
438
439             /* Getting message */
440             else if((strncmp(pieces, "Message ", 8) == 0) &&
441                     (done_message == 0))
442             {
443                 pieces+=8;
444                 done_message = 1;
445
446                 lf->log = pieces;
447
448                 /* Getting the closing brackets */
449                 pieces = strchr(pieces, ']');
450                 if(pieces)
451                 {
452                     *pieces = '\0';
453                     pieces++;
454                 }
455                 /* Invalid log closure */
456                 else
457                 {
458                     break;
459                 }
460             }
461
462             /* Getting hostname */
463             else if(strncmp(pieces, "Host ", 5) == 0)
464             {
465                 pieces+=5;
466                 lf->hostname = pieces;
467
468                 /* Getting the closing brackets */
469                 pieces = strchr(pieces, ']');
470                 if(pieces)
471                 {
472                     *pieces = '\0';
473                     pieces++;
474                 }
475
476                 /* Invalid hostname */
477                 else
478                 {
479                     lf->hostname = NULL;
480                 }
481                 break;
482             }
483
484             /* Getting next entry */
485             pieces = strchr(pieces, '[');
486         }
487     }
488
489     /* Checking for squid date format
490      * 1140804070.368  11623
491      * seconds from 00:00:00 1970-01-01 UTC
492      */
493     else if((loglen > 32) &&
494             (pieces[0] == '1') &&
495             (pieces[10] == '.') &&
496             (pieces[14] == ' ') &&
497             (isdigit((int)pieces[13])) &&
498             (isdigit((int)pieces[1])) &&
499             ((pieces[21] == ' ')||(pieces[22] == ' ')))
500     {
501         lf->log+=14;
502
503         /* We need to start at the size of the event */
504         while(*lf->log == ' ')
505         {
506             lf->log++;
507         }
508     }
509
510
511     /* Every message must be in the format
512      * hostname->location or
513      * (agent) ip->location.
514      */
515
516
517     /* Setting hostname for local messages */
518     if(lf->location[0] == '(')
519     {
520         /* Messages from an agent */
521         lf->hostname = lf->location;
522     }
523     else if(lf->hostname == NULL)
524     {
525         lf->hostname = __shost;
526     }
527
528
529     /* Setting up the event data */
530     lf->time = c_time;
531     p = localtime(&c_time);
532
533
534
535     /* Assign hour, day, year and month values */
536     lf->day = p->tm_mday;
537     lf->year = p->tm_year+1900;
538     strncpy(lf->mon,month[p->tm_mon],3);
539     snprintf(lf->hour, 9, "%02d:%02d:%02d",
540                           p->tm_hour,
541                           p->tm_min,
542                           p->tm_sec);
543
544
545
546     /* Setting the global hour/weekday */
547     __crt_hour = p->tm_hour;
548     __crt_wday = p->tm_wday;
549
550
551
552     #ifdef TESTRULE
553     if(!alert_only)
554     {
555         print_out("**Phase 1: Completed pre-decoding.");
556         print_out("       full event: '%s'", lf->full_log);
557         print_out("       hostname: '%s'", lf->hostname);
558         print_out("       program_name: '%s'", lf->program_name);
559         print_out("       log: '%s'", lf->log);
560     }
561     #endif
562     return(0);
563
564 }
565
566 /* EOF */