~ubuntu-branches/ubuntu/oneiric/syslog-ng/oneiric

« back to all changes in this revision

Viewing changes to lib/filter.c

  • Committer: Bazaar Package Importer
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2011-05-16 22:02:46 UTC
  • mfrom: (26.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110516220246-nknmeu831n49bx1z
Tags: 3.2.4-1
* New upstream release, fixing infinite loop via PCRE and global. No CVE
  number yet, Vigil@nce id is 10648.
* Remove all patches, they were applied upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2002-2010 BalaBit IT Ltd, Budapest, Hungary
 
3
 * Copyright (c) 1998-2010 Balázs Scheidler
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2.1 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 *
 
19
 * As an additional exemption you are allowed to compile & link against the
 
20
 * OpenSSL libraries as published by the OpenSSL project. See the file
 
21
 * COPYING for details.
 
22
 *
 
23
 */
 
24
  
 
25
#include "filter.h"
 
26
#include "syslog-names.h"
 
27
#include "messages.h"
 
28
#include "cfg.h"
 
29
#include "logprocess.h"
 
30
#include "gsocket.h"
 
31
#include "misc.h"
 
32
#include "tags.h"
 
33
#include "filter-expr-grammar.h"
 
34
 
 
35
#include <regex.h>
 
36
#include <string.h>
 
37
#include <stdlib.h>
 
38
 
 
39
typedef struct _LogFilterRule
 
40
{
 
41
  LogProcessRule super;
 
42
  FilterExprNode *expr;
 
43
} LogFilterRule;
 
44
 
 
45
/****************************************************************
 
46
 * Filter expression nodes
 
47
 ****************************************************************/
 
48
 
 
49
gboolean
 
50
filter_expr_eval(FilterExprNode *self, LogMessage *msg)
 
51
{
 
52
  gboolean res;
 
53
  
 
54
  res = self->eval(self, msg);
 
55
  msg_debug("Filter node evaluation result",
 
56
            evt_tag_str("filter_result", res ? "match" : "not-match"),
 
57
            evt_tag_str("filter_type", self->type),
 
58
            NULL);
 
59
  return res;
 
60
}
 
61
 
 
62
void
 
63
filter_expr_free(FilterExprNode *self)
 
64
{
 
65
  if (self->free_fn)
 
66
    self->free_fn(self);
 
67
  else
 
68
    g_free(self);
 
69
}
 
70
 
 
71
typedef struct _FilterOp
 
72
{
 
73
  FilterExprNode super;
 
74
  FilterExprNode *left, *right;
 
75
} FilterOp;
 
76
 
 
77
static void
 
78
fop_free(FilterExprNode *s)
 
79
{
 
80
  FilterOp *self = (FilterOp *) s;
 
81
  
 
82
  filter_expr_free(self->left);
 
83
  filter_expr_free(self->right);
 
84
  g_free(self);
 
85
}
 
86
 
 
87
static gboolean
 
88
fop_or_eval(FilterExprNode *s, LogMessage *msg)
 
89
{
 
90
  FilterOp *self = (FilterOp *) s;
 
91
  
 
92
  return (filter_expr_eval(self->left, msg) || filter_expr_eval(self->right, msg)) ^ s->comp;
 
93
}
 
94
 
 
95
FilterExprNode *
 
96
fop_or_new(FilterExprNode *e1, FilterExprNode *e2)
 
97
{
 
98
  FilterOp *self = g_new0(FilterOp, 1);
 
99
  
 
100
  self->super.eval = fop_or_eval;
 
101
  self->super.free_fn = fop_free;
 
102
  self->super.modify = e1->modify || e2->modify;
 
103
  self->left = e1;
 
104
  self->right = e2;
 
105
  self->super.type = "OR";
 
106
  return &self->super;
 
107
}
 
108
 
 
109
static gboolean
 
110
fop_and_eval(FilterExprNode *s, LogMessage *msg)
 
111
{
 
112
  FilterOp *self = (FilterOp *) s;
 
113
  
 
114
  return (filter_expr_eval(self->left, msg) && filter_expr_eval(self->right, msg)) ^ s->comp;
 
115
}
 
116
 
 
117
FilterExprNode *
 
118
fop_and_new(FilterExprNode *e1, FilterExprNode *e2)
 
119
{
 
120
  FilterOp *self = g_new0(FilterOp, 1);
 
121
  
 
122
  self->super.eval = fop_and_eval;
 
123
  self->super.free_fn = fop_free;
 
124
  self->super.modify = e1->modify || e2->modify;
 
125
  self->left = e1;
 
126
  self->right = e2;
 
127
  self->super.type = "AND";
 
128
  return &self->super;
 
129
}
 
130
 
 
131
#define FCMP_EQ  0x0001
 
132
#define FCMP_LT  0x0002
 
133
#define FCMP_GT  0x0004
 
134
#define FCMP_NUM 0x0010
 
135
 
 
136
typedef struct _FilterCmp
 
137
{
 
138
  FilterExprNode super;
 
139
  LogTemplate *left, *right;
 
140
  GString *left_buf, *right_buf;
 
141
  gint cmp_op;
 
142
} FilterCmp;
 
143
 
 
144
gboolean
 
145
fop_cmp_eval(FilterExprNode *s, LogMessage *msg)
 
146
{
 
147
  FilterCmp *self = (FilterCmp *) s;
 
148
  gboolean result = FALSE;
 
149
  gint cmp;
 
150
 
 
151
  log_template_format(self->left, msg, NULL, LTZ_LOCAL, 0, self->left_buf);
 
152
  log_template_format(self->right, msg, NULL, LTZ_LOCAL, 0, self->right_buf);
 
153
 
 
154
  if (self->cmp_op & FCMP_NUM)
 
155
    {
 
156
      gint l, r;
 
157
 
 
158
      l = atoi(self->left_buf->str);
 
159
      r = atoi(self->right_buf->str);
 
160
      if (l == r)
 
161
        cmp = 0;
 
162
      else if (l > r)
 
163
        cmp = -1;
 
164
      else
 
165
        cmp = 1;
 
166
    }
 
167
  else
 
168
    {
 
169
      cmp = strcmp(self->left_buf->str, self->right_buf->str);
 
170
    }
 
171
 
 
172
  if (cmp == 0)
 
173
    {
 
174
      result = self->cmp_op & FCMP_EQ;
 
175
    }
 
176
  else if (cmp < 0)
 
177
    {
 
178
      result = self->cmp_op & FCMP_LT || self->cmp_op == 0;
 
179
    }
 
180
  else
 
181
    {
 
182
      result = self->cmp_op & FCMP_GT || self->cmp_op == 0;
 
183
    }
 
184
  return result ^ s->comp;
 
185
}
 
186
 
 
187
void
 
188
fop_cmp_free(FilterExprNode *s)
 
189
{
 
190
  FilterCmp *self = (FilterCmp *) s;
 
191
 
 
192
  log_template_unref(self->left);
 
193
  log_template_unref(self->right);
 
194
  g_string_free(self->left_buf, TRUE);
 
195
  g_string_free(self->right_buf, TRUE);
 
196
  g_free(self);
 
197
}
 
198
 
 
199
FilterExprNode *
 
200
fop_cmp_new(LogTemplate *left, LogTemplate *right, gint op)
 
201
{
 
202
  FilterCmp *self = g_new0(FilterCmp, 1);
 
203
 
 
204
  self->super.eval = fop_cmp_eval;
 
205
  self->super.free_fn = fop_cmp_free;
 
206
  self->left = left;
 
207
  self->right = right;
 
208
  self->left_buf = g_string_sized_new(32);
 
209
  self->right_buf = g_string_sized_new(32);
 
210
  self->super.type = "CMP";
 
211
 
 
212
  switch (op)
 
213
    {
 
214
    case KW_NUM_LT:
 
215
      self->cmp_op = FCMP_NUM;
 
216
    case KW_LT:
 
217
      self->cmp_op = FCMP_LT;
 
218
      break;
 
219
 
 
220
    case KW_NUM_LE:
 
221
      self->cmp_op = FCMP_NUM;
 
222
    case KW_LE:
 
223
      self->cmp_op = FCMP_LT | FCMP_EQ;
 
224
      break;
 
225
 
 
226
    case KW_NUM_EQ:
 
227
      self->cmp_op = FCMP_NUM;
 
228
    case KW_EQ:
 
229
      self->cmp_op = FCMP_EQ;
 
230
      break;
 
231
 
 
232
    case KW_NUM_NE:
 
233
      self->cmp_op = FCMP_NUM;
 
234
    case KW_NE:
 
235
      self->cmp_op = 0;
 
236
      break;
 
237
 
 
238
    case KW_NUM_GE:
 
239
      self->cmp_op = FCMP_NUM;
 
240
    case KW_GE:
 
241
      self->cmp_op = FCMP_GT | FCMP_EQ;
 
242
      break;
 
243
 
 
244
    case KW_NUM_GT:
 
245
      self->cmp_op = FCMP_NUM;
 
246
    case KW_GT:
 
247
      self->cmp_op = FCMP_GT;
 
248
      break;
 
249
    }
 
250
  return &self->super;
 
251
}
 
252
 
 
253
 
 
254
typedef struct _FilterPri
 
255
{
 
256
  FilterExprNode super;
 
257
  guint32 valid;
 
258
} FilterPri;
 
259
 
 
260
static gboolean
 
261
filter_facility_eval(FilterExprNode *s, LogMessage *msg)
 
262
{
 
263
  FilterPri *self = (FilterPri *) s;
 
264
  guint32 fac_num = (msg->pri & LOG_FACMASK) >> 3;
 
265
  
 
266
  if (G_UNLIKELY(self->valid & 0x80000000))
 
267
    {
 
268
      /* exact number specified */
 
269
      return ((self->valid & ~0x80000000) == fac_num) ^ s->comp;
 
270
    }
 
271
  else
 
272
    {
 
273
      return !!(self->valid & (1 << fac_num)) ^ self->super.comp;
 
274
    }
 
275
  return self->super.comp;
 
276
}
 
277
 
 
278
FilterExprNode *
 
279
filter_facility_new(guint32 facilities)
 
280
{
 
281
  FilterPri *self = g_new0(FilterPri, 1);
 
282
 
 
283
  self->super.eval = filter_facility_eval;
 
284
  self->valid = facilities;
 
285
  self->super.type = "facility";
 
286
  return &self->super;
 
287
}
 
288
 
 
289
static gboolean
 
290
filter_level_eval(FilterExprNode *s, LogMessage *msg)
 
291
{
 
292
  FilterPri *self = (FilterPri *) s;
 
293
  guint32 pri = msg->pri & LOG_PRIMASK;
 
294
  
 
295
  return !!((1 << pri) & self->valid) ^ self->super.comp;
 
296
}
 
297
 
 
298
FilterExprNode *
 
299
filter_level_new(guint32 levels)
 
300
{
 
301
  FilterPri *self = g_new0(FilterPri, 1);
 
302
 
 
303
  self->super.eval = filter_level_eval;
 
304
  self->valid = levels;
 
305
  self->super.type = "level";
 
306
  return &self->super;
 
307
}
 
308
 
 
309
static gboolean
 
310
filter_re_eval_string(FilterExprNode *s, LogMessage *msg, gint value_handle, const gchar *str, gssize str_len)
 
311
{
 
312
  FilterRE *self = (FilterRE *) s;
 
313
 
 
314
  if (str_len < 0)
 
315
    str_len = strlen(str);
 
316
 
 
317
  return log_matcher_match(self->matcher, msg, value_handle, str, str_len) ^ self->super.comp;
 
318
}
 
319
 
 
320
static gboolean
 
321
filter_re_eval(FilterExprNode *s, LogMessage *msg)
 
322
{
 
323
  FilterRE *self = (FilterRE *) s;
 
324
  const gchar *value;
 
325
  gssize len = 0;
 
326
  
 
327
  value = log_msg_get_value(msg, self->value_handle, &len);
 
328
  
 
329
  value = APPEND_ZERO(value, len);
 
330
  return filter_re_eval_string(s, msg, self->value_handle, value, len);
 
331
}
 
332
 
 
333
 
 
334
static void
 
335
filter_re_free(FilterExprNode *s)
 
336
{
 
337
  FilterRE *self = (FilterRE *) s;
 
338
  
 
339
  log_matcher_free(self->matcher);
 
340
  g_free(s);
 
341
}
 
342
 
 
343
void
 
344
filter_re_set_matcher(FilterRE *self, LogMatcher *matcher)
 
345
{
 
346
  gint flags = 0;
 
347
  if(self->matcher)
 
348
    {
 
349
      /* save the flags to use them in the new matcher */
 
350
      flags = self->matcher->flags;
 
351
      log_matcher_free(self->matcher);
 
352
    }
 
353
   self->matcher = matcher;
 
354
 
 
355
   filter_re_set_flags(self, flags);
 
356
}
 
357
 
 
358
void
 
359
filter_re_set_flags(FilterRE *self, gint flags)
 
360
{
 
361
  /* if there is only a flags() param, we must crete the default matcher*/
 
362
  if(!self->matcher)
 
363
    self->matcher = log_matcher_posix_re_new();
 
364
  if (flags & LMF_STORE_MATCHES)
 
365
    self->super.modify = TRUE;
 
366
  log_matcher_set_flags(self->matcher, flags | LMF_MATCH_ONLY);
 
367
}
 
368
 
 
369
gboolean
 
370
filter_re_set_regexp(FilterRE *self, gchar *re)
 
371
{
 
372
  if(!self->matcher)
 
373
    self->matcher = log_matcher_posix_re_new();
 
374
 
 
375
  return log_matcher_compile(self->matcher, re);
 
376
}
 
377
 
 
378
FilterExprNode *
 
379
filter_re_new(NVHandle value_handle)
 
380
{
 
381
  FilterRE *self = g_new0(FilterRE, 1);
 
382
 
 
383
  self->value_handle = value_handle;
 
384
  self->super.eval = filter_re_eval;
 
385
  self->super.free_fn = filter_re_free;
 
386
  return &self->super;
 
387
}
 
388
 
 
389
static gboolean
 
390
filter_match_eval(FilterExprNode *s, LogMessage *msg)
 
391
{
 
392
  FilterRE *self = (FilterRE *) s;
 
393
  gchar *str;
 
394
  gboolean res;
 
395
 
 
396
  if (G_UNLIKELY(!self->value_handle))
 
397
    {
 
398
      const gchar *pid;
 
399
      gssize pid_len;
 
400
 
 
401
      pid = log_msg_get_value(msg, LM_V_PID, &pid_len);
 
402
 
 
403
      /* compatibility mode */
 
404
      str = g_strdup_printf("%s%s%s%s: %s", 
 
405
                            log_msg_get_value(msg, LM_V_PROGRAM, NULL),
 
406
                            pid_len > 0 ? "[" : "",
 
407
                            pid,
 
408
                            pid_len > 0 ? "]" : "",
 
409
                            log_msg_get_value(msg, LM_V_MESSAGE, NULL));
 
410
      res = filter_re_eval_string(s, msg, LM_V_NONE, str, -1);
 
411
      g_free(str);
 
412
    }
 
413
  else
 
414
    {
 
415
      res = filter_re_eval(s, msg);
 
416
    }
 
417
  return res;
 
418
}
 
419
 
 
420
FilterExprNode *
 
421
filter_match_new()
 
422
{
 
423
  FilterRE *self = g_new0(FilterRE, 1);
 
424
 
 
425
  self->super.free_fn = filter_re_free;
 
426
  self->super.eval = filter_match_eval;
 
427
  return &self->super;
 
428
}
 
429
 
 
430
typedef struct _FilterCall
 
431
{
 
432
  FilterExprNode super;
 
433
  GString *rule;
 
434
  GlobalConfig *cfg;
 
435
  gboolean error_logged;
 
436
} FilterCall;
 
437
 
 
438
static gboolean
 
439
filter_call_eval(FilterExprNode *s, LogMessage *msg)
 
440
{
 
441
  FilterCall *self = (FilterCall *) s;
 
442
  LogFilterRule *rule;
 
443
  
 
444
  rule = g_hash_table_lookup(self->cfg->filters, self->rule->str);
 
445
  
 
446
  if (rule)
 
447
    {
 
448
      return filter_expr_eval(rule->expr, msg) ^ s->comp;
 
449
    }
 
450
  else
 
451
    {
 
452
      if (!self->error_logged)
 
453
        {
 
454
          msg_error("Referenced filter rule not found",
 
455
                    evt_tag_str("rule", self->rule->str),
 
456
                    NULL);
 
457
          self->error_logged = TRUE;
 
458
        }
 
459
      return 1 ^ s->comp;
 
460
    }
 
461
}
 
462
 
 
463
static void
 
464
filter_call_free(FilterExprNode *s)
 
465
{
 
466
  FilterCall *self = (FilterCall *) s;
 
467
  
 
468
  g_string_free(self->rule, TRUE);
 
469
  g_free((gchar *) self->super.type);
 
470
  g_free(self);
 
471
}
 
472
 
 
473
FilterExprNode *
 
474
filter_call_new(gchar *rule, GlobalConfig *cfg)
 
475
{
 
476
  FilterCall *self = g_new0(FilterCall, 1);
 
477
  
 
478
  self->super.eval = filter_call_eval;
 
479
  self->super.free_fn = filter_call_free;
 
480
  self->rule = g_string_new(rule);
 
481
  self->cfg = cfg;
 
482
  self->super.type = g_strdup_printf("filter(%s)", rule);
 
483
  return &self->super;
 
484
}
 
485
 
 
486
 
 
487
typedef struct _FilterNetmask
 
488
{
 
489
  FilterExprNode super;
 
490
  struct in_addr address;
 
491
  struct in_addr netmask;
 
492
} FilterNetmask;
 
493
 
 
494
static gboolean
 
495
filter_netmask_eval(FilterExprNode *s, LogMessage *msg)
 
496
{
 
497
  FilterNetmask *self = (FilterNetmask *) s;
 
498
  struct in_addr addr;
 
499
  
 
500
  if (msg->saddr && g_sockaddr_inet_check(msg->saddr))
 
501
    {
 
502
      addr = ((struct sockaddr_in *) &msg->saddr->sa)->sin_addr;
 
503
    }
 
504
  else if (!msg->saddr || msg->saddr->sa.sa_family == AF_UNIX)
 
505
    {
 
506
      addr.s_addr = htonl(INADDR_LOOPBACK);
 
507
    }
 
508
  else
 
509
    {
 
510
      /* no address information, return FALSE */
 
511
      return s->comp;
 
512
    }
 
513
  return ((addr.s_addr & self->netmask.s_addr) == (self->address.s_addr)) ^ s->comp;
 
514
 
 
515
}
 
516
 
 
517
FilterExprNode *
 
518
filter_netmask_new(gchar *cidr)
 
519
{
 
520
  FilterNetmask *self = g_new0(FilterNetmask, 1);
 
521
  gchar buf[32];
 
522
  gchar *slash;
 
523
  
 
524
  slash = strchr(cidr, '/');
 
525
  if (strlen(cidr) >= sizeof(buf) || !slash)
 
526
    {
 
527
      g_inet_aton(cidr, &self->address);
 
528
      self->netmask.s_addr = htonl(0xFFFFFFFF);
 
529
    }
 
530
  else
 
531
    {
 
532
      strncpy(buf, cidr, slash - cidr + 1);
 
533
      buf[slash - cidr] = 0;
 
534
      g_inet_aton(buf, &self->address);
 
535
      if (strchr(slash + 1, '.'))
 
536
        {
 
537
          g_inet_aton(slash + 1, &self->netmask);
 
538
        }
 
539
      else
 
540
        {
 
541
          gint prefix = strtol(slash + 1, NULL, 10);
 
542
          if (prefix == 32)
 
543
            self->netmask.s_addr = htonl(0xFFFFFFFF);
 
544
          else
 
545
            self->netmask.s_addr = htonl(((1 << prefix) - 1) << (32 - prefix));
 
546
        }
 
547
    }
 
548
  self->address.s_addr &= self->netmask.s_addr;
 
549
  self->super.eval = filter_netmask_eval;
 
550
  return &self->super;
 
551
}
 
552
 
 
553
typedef struct _FilterTags
 
554
{
 
555
  FilterExprNode super;
 
556
  GArray *tags;
 
557
} FilterTags;
 
558
 
 
559
static gboolean
 
560
filter_tags_eval(FilterExprNode *s, LogMessage *msg)
 
561
{
 
562
  FilterTags *self = (FilterTags *)s;
 
563
  gint i;
 
564
 
 
565
  for (i = 0; i < self->tags->len; i++)
 
566
    {
 
567
      if (log_msg_is_tag_by_id(msg, g_array_index(self->tags, LogTagId, i)))
 
568
        return TRUE ^ s->comp;
 
569
    }
 
570
 
 
571
  return FALSE ^ s->comp;
 
572
}
 
573
 
 
574
void
 
575
filter_tags_add(FilterExprNode *s, GList *tags)
 
576
{
 
577
  FilterTags *self = (FilterTags *)s;
 
578
  LogTagId id;
 
579
 
 
580
  while (tags)
 
581
    {
 
582
      id = log_tags_get_by_name((gchar *) tags->data);
 
583
      g_free(tags->data);
 
584
      tags = g_list_delete_link(tags, tags);
 
585
      g_array_append_val(self->tags, id);
 
586
    }
 
587
}
 
588
 
 
589
static void
 
590
filter_tags_free(FilterExprNode *s)
 
591
{
 
592
  FilterTags *self = (FilterTags *)s;
 
593
 
 
594
  g_array_free(self->tags, TRUE);
 
595
 
 
596
  g_free(self);
 
597
}
 
598
 
 
599
FilterExprNode *
 
600
filter_tags_new(GList *tags)
 
601
{
 
602
  FilterTags *self = g_new0(FilterTags, 1);
 
603
 
 
604
  self->tags = g_array_new(FALSE, FALSE, sizeof(LogTagId));
 
605
 
 
606
  filter_tags_add(&self->super, tags);
 
607
 
 
608
  self->super.eval = filter_tags_eval;
 
609
  self->super.free_fn = filter_tags_free;
 
610
  return &self->super;
 
611
}
 
612
 
 
613
 
 
614
static void
 
615
log_filter_rule_free(LogProcessRule *s)
 
616
{
 
617
  LogFilterRule *self = (LogFilterRule *) s;
 
618
  
 
619
  filter_expr_free(self->expr);
 
620
}
 
621
 
 
622
gboolean 
 
623
log_filter_rule_process(LogProcessRule *s, LogMessage *msg)
 
624
{
 
625
  LogFilterRule *self = (LogFilterRule *) s;
 
626
  gboolean res;
 
627
  
 
628
  msg_debug("Filter rule evaluation begins",
 
629
            evt_tag_str("filter_rule", self->super.name),
 
630
            NULL);
 
631
  res = filter_expr_eval(self->expr, msg);
 
632
  msg_debug("Filter rule evaluation result",
 
633
            evt_tag_str("filter_result", res ? "match" : "not-match"),
 
634
            evt_tag_str("filter_rule", self->super.name),
 
635
            NULL);
 
636
  return res;
 
637
}
 
638
 
 
639
LogProcessRule *
 
640
log_filter_rule_new(const gchar *name, FilterExprNode *expr)
 
641
{
 
642
  LogFilterRule *self = g_new0(LogFilterRule, 1);
 
643
 
 
644
  log_process_rule_init_instance(&self->super, name);
 
645
  self->super.process = log_filter_rule_process;
 
646
  self->super.free_fn = log_filter_rule_free;
 
647
  self->super.modify = expr->modify;
 
648
  self->expr = expr;
 
649
  return &self->super;
 
650
}