Coverage Report

Created: 2025-07-12 06:14

/src/opensips/blacklists.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2007 Voice Sistem SRL
3
 *
4
 * This file is part of opensips, a free SIP server.
5
 *
6
 * opensips is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * opensips 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 */
20
21
/*!
22
 * \file
23
 * \brief OpenSIPS Blacklist functions
24
 */
25
26
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30
#include <fnmatch.h>
31
#include <time.h>
32
#include <unistd.h>
33
34
#include "mem/mem.h"
35
#include "mem/shm_mem.h"
36
#include "mi/mi.h"
37
#include "dprint.h"
38
#include "socket_info.h"
39
#include "blacklists.h"
40
#include "context.h"
41
#include "timer.h"
42
#include "ut.h"
43
44
static struct bl_head *blst_heads;
45
static unsigned int bl_default_marker;
46
47
static unsigned int max_heads = 8 * sizeof(int);
48
static unsigned int used_heads;
49
50
static int bl_ctx_idx = -1;
51
52
static void delete_expired_routine(unsigned int ticks, void *param);
53
static mi_response_t *mi_print_blacklists(const mi_params_t *params,
54
                      struct mi_handler *async_hdl);
55
static mi_response_t *mi_check_all_blacklists(const mi_params_t *params,
56
                      struct mi_handler *async_hdl);
57
static mi_response_t *mi_check_blacklist(const mi_params_t *params,
58
                      struct mi_handler *async_hdl);
59
static mi_response_t *mi_add_blacklist_rule(const mi_params_t *params,
60
                      struct mi_handler *async_hdl);
61
static mi_response_t *mi_del_blacklist_rule(const mi_params_t *params,
62
                      struct mi_handler *async_hdl);
63
64
65
static const mi_export_t mi_bl_cmds[] = {
66
  { "list_blacklists", "lists all the defined (static or learned) blacklists", 0, 0, {
67
    {mi_print_blacklists, {0}},
68
    {mi_print_blacklists, {"name", 0}},
69
    {EMPTY_MI_RECIPE}
70
    }
71
  },
72
  { "check_blacklists", "returns all the blacklists where proto:IP:port pattern pair matches", 0, 0, {
73
    {mi_check_all_blacklists, {"ip", 0}},
74
    {mi_check_all_blacklists, {"proto", "ip", 0}},
75
    {mi_check_all_blacklists, {"proto", "ip", "port", 0}},
76
    {mi_check_all_blacklists, {"proto", "ip", "port", "pattern", 0}},
77
    {EMPTY_MI_RECIPE}
78
    }
79
  },
80
  { "check_blacklist", "checks whether an proto:IP:port pattern matches a blacklist", 0, 0, {
81
    {mi_check_blacklist, {"name", "ip", 0}},
82
    {mi_check_blacklist, {"name", "proto", "ip", 0}},
83
    {mi_check_blacklist, {"name", "proto", "ip", "port", 0}},
84
    {mi_check_blacklist, {"name", "proto", "ip", "port", "pattern", 0}},
85
    {EMPTY_MI_RECIPE}
86
    }
87
  },
88
  { "add_blacklist_rule", "adds a new rule to a blacklist", 0, 0, {
89
    {mi_add_blacklist_rule, {"name", "rule", 0}},
90
    {mi_add_blacklist_rule, {"name", "rule", "expire", 0}},
91
    {EMPTY_MI_RECIPE}
92
    }
93
  },
94
  { "del_blacklist_rule", "removes a rule from a blacklist", 0, 0, {
95
    {mi_del_blacklist_rule, {"name", "rule", 0}},
96
    {EMPTY_MI_RECIPE}
97
    }
98
  },
99
  {EMPTY_MI_EXPORT}
100
};
101
102
int init_black_lists(void)
103
0
{
104
0
  bl_ctx_idx = context_register_int(CONTEXT_GLOBAL, NULL);
105
0
  if (bl_ctx_idx < 0)
106
0
    return -1;
107
108
  /* register timer routine  */
109
0
  if (register_timer("blcore-expire", delete_expired_routine, 0, 1,
110
0
      TIMER_FLAG_SKIP_ON_DELAY) < 0) {
111
0
    LM_ERR("failed to register timer\n");
112
0
    return -1;
113
0
  }
114
115
  /* register MI commands */
116
0
  if (register_mi_mod("blacklists", mi_bl_cmds) < 0) {
117
0
    LM_ERR("unable to register MI cmds\n");
118
0
    return -1;
119
0
  }
120
121
0
  return 0;
122
0
}
123
124
/*
125
 * get_bl_marker() and store_bl_marker():
126
 *    easy manipulation of the blacklist bitmask stored in global context
127
 */
128
static int get_bl_marker(unsigned int *marker)
129
0
{
130
0
  if (!current_processing_ctx)
131
0
    return -1;
132
133
0
  if (marker)
134
0
    *marker = (unsigned int)context_get_int(
135
0
                       CONTEXT_GLOBAL, current_processing_ctx, bl_ctx_idx);
136
137
0
  return 0;
138
0
}
139
140
#define store_bl_marker(value) \
141
0
  (context_put_int( \
142
0
    CONTEXT_GLOBAL, current_processing_ctx, bl_ctx_idx, value))
143
144
struct bl_head *create_bl_head(const str *owner, int flags, struct bl_rule *head,
145
                      struct bl_rule *tail, str *name)
146
0
{
147
0
  unsigned int i;
148
149
0
  if (!blst_heads) {
150
0
    blst_heads = shm_malloc(max_heads * sizeof *blst_heads);
151
0
    if (!blst_heads) {
152
0
      LM_ERR("no more shared memory!\n");
153
0
      return NULL;
154
0
    }
155
0
    memset(blst_heads, 0, max_heads * sizeof *blst_heads);
156
0
  }
157
0
  i = used_heads;
158
0
  if (i == max_heads) {
159
0
    LM_ERR("too many lists\n");
160
0
    return NULL;
161
0
  }
162
163
0
  if (get_bl_head_by_name(name)) {
164
0
    LM_CRIT("duplicated name!\n");
165
0
    return NULL;
166
0
  }
167
168
0
  if (flags & BL_READONLY_LIST && flags & BL_DO_EXPIRE) {
169
0
    LM_CRIT("RO lists cannot accept EXPIRES!\n");
170
0
    return NULL;
171
0
  }
172
173
  /* copy list name */
174
0
  blst_heads[i].name.s = shm_malloc(name->len + 1);
175
0
  if (!blst_heads[i].name.s) {
176
0
    LM_ERR("no more shm memory!\n");
177
0
    return NULL;
178
0
  }
179
0
  memcpy(blst_heads[i].name.s, name->s, name->len);
180
0
  blst_heads[i].name.s[name->len] = '\0';
181
0
  blst_heads[i].name.len = name->len;
182
183
  /* build lock? */
184
0
  if (!(flags & BL_READONLY_LIST)) {
185
0
    if (!(blst_heads[i].lock = lock_init_rw())) {
186
0
      LM_ERR("failed to create lock!\n");
187
0
      shm_free(blst_heads[i].name.s);
188
0
      return NULL;
189
0
    }
190
0
  }
191
192
0
  used_heads++;
193
194
0
  blst_heads[i].owner = *owner;
195
0
  blst_heads[i].flags = flags;
196
0
  blst_heads[i].first = head;
197
0
  blst_heads[i].last = tail;
198
199
0
  if (flags & BL_BY_DEFAULT)
200
0
    bl_default_marker |= (1 << i);
201
202
0
  return blst_heads + i;
203
0
}
204
205
206
207
void destroy_black_lists(void)
208
0
{
209
0
  unsigned int i;
210
0
  struct bl_rule *p, *q;
211
212
0
  for (i = 0; i < used_heads; i++) {
213
0
    if (blst_heads[i].lock) {
214
0
      lock_destroy(blst_heads[i].lock);
215
0
      lock_dealloc(blst_heads[i].lock);
216
0
    }
217
218
0
    for (p = blst_heads[i].first; p; ) {
219
0
      q = p;
220
0
      p = p->next;
221
0
      shm_free(q);
222
0
    }
223
224
0
    if (blst_heads[i].name.s)
225
0
      shm_free(blst_heads[i].name.s);
226
227
0
    blst_heads[i].first = blst_heads[i].last = NULL;
228
0
  }
229
230
0
  if (blst_heads)
231
0
    shm_free(blst_heads);
232
0
}
233
234
235
236
static inline void delete_expired(struct bl_head *elem, unsigned int ticks)
237
0
{
238
0
  struct bl_rule *p, *q;
239
0
  struct bl_rule *last_no_expire;
240
241
0
  p = q = 0;
242
243
  /* get list for write */
244
0
  lock_start_write(elem->lock);
245
246
0
  if (!elem->first || elem->last->expire_end == 0)
247
0
    goto done;
248
249
0
  for (last_no_expire = 0, p = elem->first;
250
0
      p && p->expire_end == 0;
251
0
      last_no_expire = p, p = p->next);
252
253
  /* p continues from where it as left */
254
0
  for (q = 0; p; q = p, p = p->next)
255
0
    if (p->expire_end > ticks)
256
0
      break;
257
258
0
  if (!q)
259
0
    goto done; /* nothing to remove */
260
261
0
  if (!p) {
262
    /* remove everything */
263
0
    if (last_no_expire) {
264
0
      q = last_no_expire->next;
265
0
      elem->last = last_no_expire;
266
0
      last_no_expire->next = NULL;
267
0
    } else {
268
0
      q = elem->first;
269
0
      elem->first = elem->last = NULL;
270
0
    }
271
0
  } else {
272
    /* remove up to p */
273
0
    q->next = NULL;
274
0
    if (last_no_expire) {
275
0
      q = last_no_expire->next;
276
0
      last_no_expire->next = p;
277
0
    } else {
278
0
      q = elem->first;
279
0
      elem->first = p;
280
0
    }
281
0
  }
282
283
0
done:
284
0
  lock_stop_write(elem->lock);
285
286
0
  for (; q; ) {
287
0
    p = q;
288
0
    q = q->next;
289
0
    shm_free(p);
290
0
  }
291
0
}
292
293
294
295
static void delete_expired_routine(unsigned int ticks, void *param)
296
0
{
297
0
  unsigned int i;
298
299
0
  for (i = 0 ; i < used_heads ; i++)
300
0
    if (blst_heads[i].flags&BL_DO_EXPIRE && blst_heads[i].first)
301
0
        delete_expired(blst_heads + i, ticks);
302
0
}
303
304
305
306
static inline int ip_class_compare(struct net *net1, struct net *net2)
307
0
{
308
0
  unsigned int r;
309
310
0
  if (net1->ip.af == net2->ip.af){
311
    /* ipv4 & ipv6 addresses are all multiples of 4 */
312
0
    for(r=0; r<net1->ip.len/4; r++)
313
0
      if ((net1->ip.u.addr32[r]&net1->mask.u.addr32[r])!=
314
0
           (net2->ip.u.addr32[r]&net2->mask.u.addr32[r]))
315
0
        return 0;
316
0
    return 1;
317
0
  }
318
319
0
  return -1;
320
0
}
321
322
323
/*! \brief adds a new rule to a list of rules */
324
int add_rule_to_list(struct bl_rule **first, struct bl_rule **last,
325
      struct net *ip_net, str *body, unsigned short port,
326
      unsigned short proto, int flags)
327
0
{
328
0
  struct bl_rule *p;
329
0
  struct bl_rule *q;
330
331
0
  if (!first || !last || !ip_net){
332
0
    LM_ERR("wrong input parameter format\n");
333
0
    return -1;
334
0
  }
335
336
0
  if (body && body->len==0)
337
0
    body = 0;
338
339
  /* is it a duplicate? */
340
0
  for (q = *first; q; q = q->next) {
341
0
    if ( (flags==q->flags) && (port==q->port) &&
342
0
      (proto==q->proto) &&
343
0
      (ip_class_compare(ip_net, &q->ip_net)==1) &&
344
0
      ((body==NULL && q->body.s==NULL) || (body && q->body.s &&
345
0
        (body->len==q->body.len) &&
346
0
        !strncmp(body->s,q->body.s,body->len)) )
347
0
      ) {
348
0
        return 1;
349
0
    }
350
0
  }
351
352
  /* alloc memory */
353
0
  p = shm_malloc(sizeof *p + (body?(body->len + 1):0));
354
0
  if (!p) {
355
0
    LM_ERR("no more  shm memory!\n");
356
0
    return -1;
357
0
  }
358
359
  /* fill in the structure */
360
0
  p->flags = flags;
361
0
  p->ip_net = *ip_net;
362
0
  p->proto = proto;
363
0
  p->port = port;
364
0
  if (body) {
365
0
    p->body.s = (char *)(p + 1);
366
0
    memcpy(p->body.s, body->s, body->len);
367
0
    p->body.s[body->len] = '\0';
368
0
    p->body.len = body->len;
369
0
  } else {
370
0
    p->body.s = NULL;
371
0
    p->body.len = 0;
372
0
  }
373
0
  p->next = NULL;
374
0
  p->expire_end = 0;
375
376
  /* link the structure */
377
0
  if (!*first) {
378
0
    *first = *last = p;
379
0
  } else {
380
0
    (*last)->next = p;
381
0
    *last = p;
382
0
  }
383
384
0
  return 0;
385
0
}
386
387
388
static int del_rule_from_list(struct bl_head *head,
389
      struct net *ip_net, str *body, unsigned short port,
390
      unsigned short proto, int flags)
391
0
{
392
0
  struct bl_rule *r, *q;
393
0
  int ret = -1;
394
395
0
  lock_start_write(head->lock);
396
397
0
  for (q = NULL, r = head->first; r; q = r, r = r->next) {
398
0
    if ( (r->flags==flags) && (r->port==port) &&
399
0
      (r->proto==proto) &&
400
0
      (ip_class_compare(&r->ip_net, ip_net)==1) &&
401
0
      ((!r->body.s && !body->s) || ((r->body.len==body->len) &&
402
0
        r->body.s!=NULL && body->s!=NULL &&
403
0
        !strncmp(r->body.s,body->s,body->len)) )
404
0
       ) {
405
0
      if (q) {
406
0
        q->next = r->next;
407
0
      } else {
408
0
        head->first = r->next;
409
0
      }
410
0
      shm_free(r);
411
0
      ret = 0;
412
0
      break;
413
0
    }
414
0
  }
415
0
  lock_stop_write(head->lock);
416
0
  return ret;
417
0
}
418
419
static inline void rm_dups(struct bl_head *head,
420
            struct bl_rule **first, struct bl_rule **last)
421
0
{
422
0
  struct bl_rule *p, *q;
423
0
  struct bl_rule *r;
424
425
0
  for( p=0,q=*first ; q ; ) {
426
0
    for( r=head->first; r ; r = r->next) {
427
0
      if ( (r->flags==q->flags) && (r->port==q->port) &&
428
0
      (r->proto==q->proto) &&
429
0
      (ip_class_compare(&r->ip_net, &q->ip_net)==1) &&
430
0
      ((!r->body.s && !q->body.s) || ((r->body.len==q->body.len) &&
431
0
                r->body.s!=NULL && q->body.s!=NULL &&
432
0
        !strncmp(r->body.s,q->body.s,q->body.len)) )
433
0
      ) {
434
0
        break;
435
0
      }
436
0
    }
437
0
    if (r) {
438
      /* q duplicates r -> free q */
439
0
      if (q->next==NULL) *last=p;
440
0
      if (p) {
441
0
        p->next = q->next;
442
0
        shm_free(q);
443
0
        q = p->next;
444
0
      } else {
445
0
        *first = q->next;
446
0
        shm_free(q);
447
0
        q = *first;
448
0
      }
449
0
    } else {
450
0
      p=q;
451
0
      q=q->next;
452
0
    }
453
0
  }
454
0
}
455
456
457
458
static inline int reload_permanent_list(struct bl_rule *first,
459
          struct bl_rule *last,
460
          struct bl_head *head)
461
0
{
462
0
  struct bl_rule *p, *q;
463
464
  /* get list for write */
465
0
  lock_start_write(head->lock);
466
467
0
  for(p = head->first ; p ; ){
468
0
    q = p;
469
0
    p = p->next;
470
0
    shm_free(q);
471
0
  }
472
473
0
  head->first = first;
474
0
  head->last = last;
475
476
0
  lock_stop_write(head->lock);
477
478
0
  return 0;
479
0
}
480
481
482
483
/* should NOT add ANY DUPLICATES */
484
int add_list_to_head(struct bl_head *head,
485
      struct bl_rule *first, struct bl_rule *last,
486
      int truncate, int expire_limit)
487
0
{
488
0
  struct bl_rule *p;
489
0
  unsigned int expire_end = 0;
490
491
0
  if (!head || !first || !last)
492
0
    return -1;
493
494
  /* may I add to this list? */
495
0
  if (head->flags & BL_READONLY_LIST) {
496
0
    LM_CRIT("list is readonly!!!\n");
497
0
    return -1;
498
0
  }
499
500
0
  LM_DBG("adding to bl %.*s %p,%p\n",
501
0
       head->name.len, head->name.s, first, last);
502
503
  /* for expiring lists, sets the timeout */
504
0
  if (head->flags & BL_DO_EXPIRE) {
505
0
    if (expire_limit!=0) {
506
0
      expire_end = get_ticks() + expire_limit;
507
0
      for (p = first; p; p = p->next)
508
0
        p->expire_end = expire_end;
509
0
    } else {
510
0
      LM_DBG("expire is zero - rule never expires\n");
511
0
    }
512
0
  }
513
514
  /* truncate? -> just do reload */
515
0
  if (truncate)
516
0
    return reload_permanent_list( first, last, head);
517
518
  /* get list for write */
519
0
  lock_start_write(head->lock);
520
521
0
  rm_dups(head, &first, &last);
522
0
  if (!first)
523
0
    goto done;
524
525
  /* the list is built as it follows:
526
   * - rules that do not expire are always first
527
   * - rules that expire are oredered based on their expiration time
528
   */
529
530
0
  if (!head->first) {
531
0
    head->last  = last;
532
0
    head->first = first;
533
0
  } else if (!(head->flags & BL_DO_EXPIRE)) {
534
0
    head->last->next = first;
535
0
    head->last = last;
536
0
  } else if (expire_end == 0) {
537
    /* non-expiry rules are always first */
538
0
    last->next = head->first;
539
0
    head->first = first;
540
0
  } else {
541
    /* find first element with expiration */
542
0
    for (p = head->first;
543
0
      p->next && p->next->expire_end == 0;
544
0
      p = p->next);
545
0
    if (p == head->last || head->last->expire_end <= expire_end) {
546
      /* no expiration rules, add at last */
547
0
      head->last->next = first;
548
0
      head->last = last;
549
0
    } else {
550
0
      for (;; p = p->next)
551
0
        if (p->next->expire_end >= expire_end)
552
0
          break;
553
0
      last->next = p->next;
554
0
      p->next = first;
555
0
    }
556
0
  }
557
558
0
done:
559
0
  lock_stop_write(head->lock);
560
561
0
  return 0;
562
0
}
563
564
565
566
struct bl_head *get_bl_head_by_name(str *name)
567
0
{
568
0
  unsigned int i;
569
570
0
  for (i = 0; i < used_heads; i++)
571
0
    if ((name->len == blst_heads[i].name.len) &&
572
0
        !strncmp(name->s, blst_heads[i].name.s, name->len))
573
0
      return blst_heads + i;
574
575
0
  return NULL;
576
0
}
577
578
579
580
int mark_for_search(struct bl_head *list, unsigned int set)
581
0
{
582
0
  unsigned int n;
583
0
  unsigned int bl_marker;
584
585
0
  if (get_bl_marker(&bl_marker) != 0)
586
0
    return 1;
587
588
  /* is it an "all" operation? */
589
0
  if (!list) {
590
0
    store_bl_marker(set ? (unsigned int)-1 : 0);
591
0
    return 0;
592
0
  }
593
594
0
  n = list - blst_heads;
595
0
  if (list < blst_heads || n >= used_heads)
596
0
    return 1;
597
598
0
  if (set)
599
0
    store_bl_marker(bl_marker | (1 << n));
600
0
  else
601
0
    store_bl_marker(bl_marker & ~(1 << n));
602
603
0
  return 0;
604
0
}
605
606
607
608
/*
609
 * If possible, reset the bitmask stored in the current global context
610
 */
611
void reset_bl_markers(void)
612
0
{
613
0
  if (get_bl_marker(NULL) == 0)
614
0
    store_bl_marker(bl_default_marker);
615
0
}
616
617
static inline int match_bl_rule(struct ip_addr *ip, str *text,
618
            unsigned short port,
619
            unsigned short proto,
620
            struct bl_rule *p)
621
0
{
622
0
  int t_val = (p->port==0 || p->port==port) &&
623
0
    (p->proto==PROTO_NONE || p->proto==proto) &&
624
0
    (matchnet(ip, &(p->ip_net)) == 1) &&
625
0
    (p->body.s==NULL || !fnmatch(p->body.s, text->s, 0));
626
0
  return (!!(p->flags & BLR_APPLY_CONTRARY) ^ !!(t_val));
627
0
}
628
629
630
static inline int check_against_rule_list(struct ip_addr *ip, str *text,
631
            unsigned short port,
632
            unsigned short proto,
633
            int i)
634
0
{
635
0
  struct bl_rule *p;
636
0
  int ret = 0;
637
638
0
  LM_DBG("using list %.*s \n",
639
0
    blst_heads[i].name.len, blst_heads[i].name.s);
640
641
0
  if( !(blst_heads[i].flags&BL_READONLY_LIST) ) {
642
    /* get list for read */
643
0
    lock_start_read(blst_heads[i].lock);
644
0
  }
645
646
0
  for(p = blst_heads[i].first ; p ; p = p->next) {
647
0
    if(match_bl_rule(ip, text, port, proto, p)) {
648
0
      ret = 1;
649
0
      LM_DBG("matched list %.*s \n",
650
0
        blst_heads[i].name.len,blst_heads[i].name.s);
651
0
      break;
652
0
    }
653
0
  }
654
655
0
  if( !(blst_heads[i].flags&BL_READONLY_LIST) )
656
0
    lock_stop_read(blst_heads[i].lock);
657
658
0
  return ret;
659
0
}
660
661
662
663
int check_against_blacklist(struct ip_addr *ip, str *text,
664
      unsigned short port, unsigned short proto)
665
0
{
666
0
  unsigned int i;
667
0
  unsigned int bl_marker;
668
669
  /* no context -> no blacklists at all -> successful check */
670
0
  if (get_bl_marker(&bl_marker) != 0)
671
0
    return 0;
672
673
0
  for (i = 0; i < used_heads; i++)
674
0
    if (bl_marker & (1 << i) &&
675
0
        check_against_rule_list(ip, text, port, proto, i))
676
0
      return 1;
677
678
0
  return 0;
679
0
}
680
681
static int mi_print_blacklist_rule(mi_item_t *rule_item,
682
    struct bl_rule *blr, int expire)
683
0
{
684
0
  char *p;
685
0
  int len;
686
687
0
  if (add_mi_number(rule_item, MI_SSTR("flags"), blr->flags) < 0)
688
0
    return -1;
689
690
0
  p = ip_addr2a(&blr->ip_net.ip);
691
0
  len = p?strlen(p):0;
692
0
  if (add_mi_string(rule_item, MI_SSTR("IP"), p, len) < 0)
693
0
    return -1;
694
695
0
  p = ip_addr2a(&blr->ip_net.mask);
696
0
  len = p?strlen(p):0;
697
0
  if (add_mi_string(rule_item, MI_SSTR("Mask"), p, len) < 0)
698
0
    return -1;
699
700
0
  if (blr->proto == PROTO_NONE)
701
0
    p = "any";
702
0
  else
703
0
    p = proto2a(blr->proto);
704
0
  len = strlen(p);
705
0
  if (add_mi_string(rule_item, MI_SSTR("Proto"), p, len) < 0)
706
0
    return -1;
707
708
0
  if (add_mi_number(rule_item, MI_SSTR("Port"), blr->port) < 0)
709
0
    return -1;
710
711
0
  if (blr->body.s) {
712
0
    if (add_mi_string(rule_item, MI_SSTR("Match"),
713
0
        blr->body.s, blr->body.len) < 0)
714
0
      return -1;
715
0
  }
716
717
0
  if (expire && blr->expire_end && add_mi_number(rule_item,
718
0
      MI_SSTR("Expire"), (blr->expire_end - get_ticks())) < 0)
719
0
    return -1;
720
0
  return 0;
721
0
}
722
723
static int mi_print_blacklist_head(mi_item_t *list_item, struct bl_head *head)
724
0
{
725
0
  int ret = -1;
726
0
  struct bl_rule *blr;
727
0
  mi_item_t *rules_arr, *rule_item, *flags_arr;
728
729
0
  if (!(head->flags&BL_READONLY_LIST) )
730
0
    lock_start_read(head->lock);
731
732
0
  if (add_mi_string(list_item, MI_SSTR("name"),
733
0
      head->name.s, head->name.len) < 0)
734
0
    goto end;
735
736
0
  if (add_mi_string(list_item, MI_SSTR("owner"),
737
0
      head->owner.s, head->owner.len) < 0)
738
0
    goto end;
739
740
0
  flags_arr = add_mi_array(list_item, MI_SSTR("flags"));
741
0
  if (!flags_arr)
742
0
    goto end;
743
0
  if (head->flags & BL_READONLY_LIST &&
744
0
      add_mi_string(flags_arr, NULL, 0, MI_SSTR("read-only")) < 0)
745
0
    goto end;
746
0
  if (head->flags & BL_DO_EXPIRE &&
747
0
      add_mi_string(flags_arr, NULL, 0, MI_SSTR("expire")) < 0)
748
0
    goto end;
749
0
  if (head->flags & BL_BY_DEFAULT &&
750
0
      add_mi_string(flags_arr, NULL, 0, MI_SSTR("default")) < 0)
751
0
    goto end;
752
753
0
  rules_arr = add_mi_array(list_item, MI_SSTR("Rules"));
754
0
  if (!rules_arr)
755
0
    goto end;
756
757
0
  for (blr = head->first; blr; blr = blr->next) {
758
0
    rule_item = add_mi_object(rules_arr, NULL, 0);
759
0
    if (!rule_item)
760
0
      goto end;
761
762
0
    if (mi_print_blacklist_rule(rule_item, blr,
763
0
        head->flags&BL_DO_EXPIRE) < 0)
764
0
      goto end;
765
0
  }
766
767
0
  ret = 0;
768
0
end:
769
0
  if (!(head->flags&BL_READONLY_LIST) )
770
0
    lock_stop_read(head->lock);
771
0
  return ret;
772
0
}
773
774
static mi_response_t *mi_print_blacklists(const mi_params_t *params,
775
  struct mi_handler *async_hdl)
776
0
{
777
0
  mi_response_t *resp;
778
0
  mi_item_t *resp_obj;
779
0
  mi_item_t *lists_arr, *list_item;
780
0
  struct bl_head *head;
781
0
  unsigned int i;
782
0
  str name;
783
784
0
  switch (try_get_mi_string_param(params, "name", &name.s, &name.len)) {
785
0
    case -1:
786
0
      head = NULL;
787
0
      break;
788
0
    case 0:
789
0
      head = get_bl_head_by_name(&name);
790
0
      if (!head)
791
0
        return init_mi_error(404, MI_SSTR("Unknown name"));
792
0
      break;
793
0
    default:
794
0
      return NULL;
795
0
  }
796
797
0
  resp = init_mi_result_object(&resp_obj);
798
0
  if (!resp)
799
0
    return 0;
800
801
0
  if (head) {
802
    /* already have a head, print only it */
803
0
    if(mi_print_blacklist_head(resp_obj, head) < 0)
804
0
      goto error;
805
0
    return resp;
806
0
  }
807
808
0
  lists_arr = add_mi_array(resp_obj, MI_SSTR("Lists"));
809
0
  if (!lists_arr)
810
0
    goto error;
811
812
0
  for (i=0; i<used_heads; i++ ) {
813
0
    list_item = add_mi_object(lists_arr, NULL, 0);
814
0
    if (!list_item)
815
0
      goto error;
816
817
0
    if (mi_print_blacklist_head(list_item, &blst_heads[i]) < 0)
818
0
      goto error;
819
0
  }
820
821
0
  return resp;
822
823
0
error:
824
825
0
  free_mi_response(resp);
826
0
  return NULL;
827
0
}
828
829
static struct bl_head *mi_bl_get_head(const mi_params_t *params)
830
0
{
831
0
  str name;
832
833
0
  if (get_mi_string_param(params, "name", &name.s, &name.len) < 0)
834
0
    return NULL;
835
0
  return get_bl_head_by_name(&name);
836
0
}
837
838
static struct ip_addr *mi_bl_get_ip(const mi_params_t *params)
839
0
{
840
0
  str ip;
841
842
0
  if (get_mi_string_param(params, "ip", &ip.s, &ip.len) < 0)
843
0
    return NULL;
844
0
  return str2ip(&ip);
845
0
}
846
847
static int mi_bl_get_extra(const mi_params_t *params,
848
    unsigned short *proto, unsigned short *port, str *text)
849
0
{
850
0
  str proto_str;
851
0
  int tmp;
852
853
0
  switch (try_get_mi_string_param(params, "proto", &proto_str.s, &proto_str.len)) {
854
0
    case -1:
855
0
      *proto = PROTO_NONE;
856
0
      break;
857
0
    case 0:
858
0
      if (parse_proto((unsigned char *)proto_str.s,
859
0
          proto_str.len, &tmp) < 0) {
860
0
        LM_ERR("could not parse protocol %.*s\n",
861
0
            proto_str.len, proto_str.s);
862
0
        return -1;
863
0
      }
864
0
      *proto = tmp;
865
0
      break;
866
0
    default:
867
0
      return -1;
868
0
  }
869
0
  switch (try_get_mi_int_param(params, "port", &tmp)) {
870
0
    case -1:
871
0
      *port = 0;
872
0
      break;
873
0
    case 0:
874
0
      *port = tmp;
875
0
      break;
876
0
    default:
877
0
      return -1;
878
0
  }
879
0
  switch (try_get_mi_string_param(params, "pattern", &text->s, &text->len)) {
880
0
    case -1:
881
0
      text->s = NULL;
882
0
      text->len = 0;
883
0
      break;
884
0
    case 0:
885
0
      break;
886
0
    default:
887
0
      return -1;
888
0
  }
889
0
  return 0;
890
0
}
891
892
static int parse_ip_net(char *in, int len, struct net *ipnet)
893
0
{
894
0
  char *p = NULL;
895
0
  str ip_s, mask_s;
896
0
  struct ip_addr ip, *mask = NULL, *ip_tmp;
897
0
  struct net *ipnet_tmp;
898
0
  int af;
899
0
  unsigned int bitlen;
900
901
0
  p = q_memchr(in, '.', len);
902
0
  if (p)
903
0
    af = AF_INET;
904
0
  else if (q_memchr(in, ':', len)) {
905
0
    af = AF_INET6;
906
0
  } else {
907
0
    LM_ERR("Not an IP");
908
0
    return -1;
909
0
  }
910
911
0
  p = q_memchr(in, '/', len);
912
0
  if (p) {
913
0
    ip_s.s = in;
914
0
    ip_s.len = p - in;
915
0
  } else {
916
0
    ip_s.s = in;
917
0
    ip_s.len = len;
918
0
  }
919
920
0
  ip_tmp = (af == AF_INET) ? str2ip(&ip_s) : str2ip6(&ip_s);
921
0
  if (!ip_tmp) {
922
0
    LM_ERR("Invalid IP address\n");
923
0
    return -1;
924
0
  }
925
926
  /* save the IP */
927
0
  ip = *ip_tmp;
928
929
0
  if (p) {
930
0
    mask_s.s = p + 1;
931
0
    mask_s.len = len - ip_s.len - 1;
932
0
    if (!mask_s.s || mask_s.len == 0) {
933
0
      LM_ERR("Empty netmask\n");
934
0
      return -1;
935
0
    }
936
0
    if ((p = (af == AF_INET)?
937
0
      q_memchr(p, '.', len-(p-in)+1):
938
0
      q_memchr(p, ':', len-(p-in)+1)) != NULL) {
939
      /* has net */
940
0
      mask = (af == AF_INET) ? str2ip(&mask_s) : str2ip6(&mask_s);
941
0
      if (!mask) {
942
0
        LM_ERR("Invalid netmask\n");
943
0
        return -1;
944
0
      }
945
0
      ipnet_tmp = mk_net(&ip, mask);
946
0
    } else {
947
0
      if (str2int(&mask_s, &bitlen) < 0) {
948
0
        LM_ERR("Invalid netmask bitlen\n");
949
0
        return -1;
950
0
      }
951
952
0
      ipnet_tmp = mk_net_bitlen(&ip, bitlen);
953
0
    }
954
0
  } else {
955
0
    ipnet_tmp = mk_net_bitlen(&ip, ip.len*8);
956
0
  }
957
958
0
  *ipnet = *ipnet_tmp;
959
0
  pkg_free(ipnet_tmp);
960
961
0
  return 0;
962
0
}
963
964
static int mi_bl_get_rule(const mi_params_t *params,
965
    struct net *ip_net, unsigned short *proto,
966
    unsigned short *port, str *text, int *flags)
967
0
{
968
0
  str rule, token;
969
0
  char *p;
970
0
  int tmp;
971
972
0
  *proto = PROTO_NONE;
973
0
  *port = 0;
974
0
  text->s = NULL;
975
0
  text->len = 0;
976
0
  *flags = 0;
977
978
0
  if (get_mi_string_param(params, "rule", &rule.s, &rule.len) < 0) {
979
0
    LM_INFO("command does not contain a rule\n");
980
0
    return -1;
981
0
  }
982
0
  trim_leading(&rule);
983
0
  if (rule.len > 0 && rule.s[0] == '!') {
984
0
    rule.s++;
985
0
    rule.len--;
986
0
    *flags = BLR_APPLY_CONTRARY;
987
0
  }
988
  /* first token should always be ip or net*/
989
0
  p = q_memchr(rule.s, ',', rule.len);
990
0
  token.s = rule.s;
991
0
  token.len = (p? (p - rule.s): rule.len);
992
0
  rule.s += token.len + 1;
993
0
  rule.len -= token.len + 1;
994
0
  if (str_casematch_nt(&token, "any")) {
995
0
    *proto = PROTO_NONE;
996
0
  } else if (parse_proto((unsigned char *)token.s, token.len, &tmp) >= 0) {
997
    /* valid proto */
998
0
    *proto = tmp;
999
1000
    /* advance to next token */
1001
0
    p = q_memchr(rule.s, ',', rule.len);
1002
0
    token.s = rule.s;
1003
0
    token.len = (p? (p - rule.s): rule.len);
1004
0
    rule.s += token.len + 1;
1005
0
    rule.len -= token.len + 1;
1006
0
  }
1007
0
  if (parse_ip_net(token.s, token.len, ip_net) < 0)
1008
0
    return -1;
1009
0
  if (rule.len <= 0)
1010
0
    return 0;
1011
1012
0
  p = q_memchr(rule.s, ',', rule.len);
1013
0
  token.s = rule.s;
1014
0
  token.len = (p? (p - rule.s): rule.len);
1015
1016
1017
  /* we should have a port here */
1018
0
  if (str2int(&token, (unsigned int *)&tmp) < 0) {
1019
0
    LM_INFO("invalid port %.*s\n", token.len, token.s);
1020
0
    return -1;
1021
0
  }
1022
0
  *port = tmp;
1023
0
  text->s = rule.s + token.len + 1;
1024
0
  text->len = rule.len - token.len - 1;
1025
0
  if (text->len <= 0) {
1026
0
    text->s = NULL;
1027
0
    text->len = 0;
1028
0
  }
1029
1030
1031
0
  return 0;
1032
0
}
1033
1034
1035
static mi_response_t *mi_check_all_blacklists(const mi_params_t *params,
1036
    struct mi_handler *async_hdl)
1037
0
{
1038
0
  mi_response_t *resp;
1039
0
  mi_item_t *resp_arr;
1040
0
  unsigned short proto, port;
1041
0
  struct ip_addr *ip;
1042
0
  str text, text_nt;
1043
0
  unsigned int i;
1044
1045
0
  ip = mi_bl_get_ip(params);
1046
0
  if (!ip)
1047
0
    return init_mi_error(400, MI_SSTR("Missing or bad IP"));
1048
1049
0
  if (mi_bl_get_extra(params, &proto, &port, &text) < 0)
1050
0
    return init_mi_error(404, MI_SSTR("Bad params"));
1051
1052
0
  resp = init_mi_result_array(&resp_arr);
1053
0
  if (!resp)
1054
0
    return NULL;
1055
1056
  /* if there is a text, duplicate it to obtain NULL-terminated */
1057
0
  if (text.len) {
1058
0
    if (pkg_nt_str_dup(&text_nt, &text) < 0) {
1059
0
      free_mi_response(resp);
1060
0
      return NULL;
1061
0
    }
1062
0
  } else {
1063
0
    text_nt.s = "";
1064
0
    text_nt.len = 0;
1065
0
  }
1066
1067
0
  for (i = 0; i < used_heads; i++) {
1068
0
    if (!check_against_rule_list(ip, &text_nt, port, proto, i))
1069
0
      continue;
1070
0
    if (add_mi_string(resp_arr, NULL, 0, blst_heads[i].name.s,
1071
0
        blst_heads[i].name.len) < 0) {
1072
0
      LM_ERR("cannot add blacklist %.*s\n",
1073
0
          blst_heads[i].name.len, blst_heads[i].name.s);
1074
0
      free_mi_response(resp);
1075
0
      resp = NULL;
1076
0
      goto end;
1077
0
    }
1078
0
  }
1079
1080
0
end:
1081
0
  if (text.len)
1082
0
    pkg_free(text_nt.s);
1083
0
  return resp;
1084
0
}
1085
1086
static mi_response_t *mi_check_blacklist(const mi_params_t *params,
1087
    struct mi_handler *async_hdl)
1088
0
{
1089
0
  static mi_response_t *resp;
1090
0
  unsigned short proto, port;
1091
0
  mi_item_t *obj;
1092
0
  struct bl_head *head;
1093
0
  struct bl_rule *p;
1094
0
  struct ip_addr *ip;
1095
0
  str text, text_nt;
1096
1097
0
  ip = mi_bl_get_ip(params);
1098
0
  if (!ip)
1099
0
    return init_mi_error(400, MI_SSTR("Missing or bad IP"));
1100
1101
0
  head = mi_bl_get_head(params);
1102
0
  if (!head)
1103
0
    return init_mi_error(400, MI_SSTR("Missing or bad blacklist name"));
1104
1105
0
  if (mi_bl_get_extra(params, &proto, &port, &text) < 0)
1106
0
    return init_mi_error(404, MI_SSTR("Bad params"));
1107
1108
  /* if there is a text, duplicate it to obtain NULL-terminated */
1109
0
  if (text.len) {
1110
0
    if (pkg_nt_str_dup(&text_nt, &text) < 0)
1111
0
      return NULL;
1112
0
  } else {
1113
0
    text_nt.s = "";
1114
0
    text_nt.len = 0;
1115
0
  }
1116
1117
0
  if (!(head->flags&BL_READONLY_LIST))
1118
0
    lock_start_read(head->lock);
1119
1120
0
  for(p = head->first; p; p = p->next)
1121
0
    if(match_bl_rule(ip, &text_nt, port, proto, p))
1122
0
      break;
1123
1124
0
  if (text.len)
1125
0
    pkg_free(text_nt.s);
1126
1127
0
  if (p) {
1128
0
    resp = init_mi_result_object(&obj);
1129
0
    if (resp && mi_print_blacklist_rule(obj, p, head->flags&BL_DO_EXPIRE) < 0) {
1130
0
      free_mi_response(resp);
1131
0
      resp = NULL;
1132
0
    }
1133
1134
0
  } else {
1135
0
    resp = init_mi_error(404, MI_SSTR("Not Matched"));
1136
0
  }
1137
0
  if (!(head->flags&BL_READONLY_LIST))
1138
0
    lock_stop_read(head->lock);
1139
0
  return resp;
1140
0
}
1141
1142
static mi_response_t *mi_add_blacklist_rule(const mi_params_t *params,
1143
                      struct mi_handler *async_hdl)
1144
0
{
1145
0
  struct bl_head *head;
1146
0
  struct bl_rule *list = NULL;
1147
0
  struct net ip_net;
1148
0
  unsigned short proto, port;
1149
0
  int expire, flags;
1150
0
  str text;
1151
1152
0
  head = mi_bl_get_head(params);
1153
0
  if (!head)
1154
0
    return init_mi_error(400, MI_SSTR("Missing or bad blacklist name"));
1155
  /* if a read-only list, we cannot modify */
1156
0
  if (head->flags & BL_READONLY_LIST)
1157
0
    return init_mi_error(403, MI_SSTR("Cannot modify read-only blacklist"));
1158
1159
0
  if (mi_bl_get_rule(params, &ip_net, &proto, &port, &text, &flags) < 0)
1160
0
    return init_mi_error(404, MI_SSTR("Bad rule"));
1161
1162
0
  switch (try_get_mi_int_param(params, "expire", &expire)) {
1163
0
    case -1:
1164
0
      expire = 0;
1165
0
      break;
1166
0
    case 0:
1167
0
      if (expire <= 0)
1168
0
        return init_mi_error(404, MI_SSTR("Bad expire value"));
1169
0
      if (!(head->flags & BL_DO_EXPIRE))
1170
0
        return init_mi_error(404, MI_SSTR("Blacklist without expire support"));
1171
0
      break;
1172
0
    default:
1173
0
      return NULL;
1174
0
  }
1175
0
  if (add_rule_to_list(&list, &list, &ip_net, &text, port, proto, flags) != 0) {
1176
0
    LM_ERR("cannot build blacklist rule!\n");
1177
0
    return NULL;
1178
0
  }
1179
0
  if (add_list_to_head(head, list, list, 0, expire) < 0) {
1180
0
    LM_ERR("cannot add blacklist rule!\n");
1181
0
    return NULL;
1182
0
  }
1183
0
  return init_mi_result_ok();
1184
0
}
1185
1186
static mi_response_t *mi_del_blacklist_rule(const mi_params_t *params,
1187
                      struct mi_handler *async_hdl)
1188
0
{
1189
0
  struct bl_head *head;
1190
0
  unsigned short proto, port;
1191
0
  struct net ip_net;
1192
0
  str text;
1193
0
  int flags;
1194
1195
0
  head = mi_bl_get_head(params);
1196
0
  if (!head)
1197
0
    return init_mi_error(400, MI_SSTR("Missing or bad blacklist name"));
1198
  /* if a read-only list, we cannot modify */
1199
0
  if (head->flags & BL_READONLY_LIST)
1200
0
    return init_mi_error(403, MI_SSTR("Cannot modify read-only blacklist"));
1201
1202
0
  if (mi_bl_get_rule(params, &ip_net, &proto, &port, &text, &flags) < 0)
1203
0
    return init_mi_error(404, MI_SSTR("Bad rule"));
1204
1205
0
  if (del_rule_from_list(head, &ip_net, &text, port, proto, flags) != 0)
1206
0
    return init_mi_error(404, MI_SSTR("Rule not found"));
1207
1208
0
  return init_mi_result_ok();
1209
0
}
1210
1211
int w_check_blacklist(struct sip_msg *msg, struct bl_head *head,
1212
    struct ip_addr *ip, int *_port, unsigned short _proto, str *_pattern)
1213
0
{
1214
0
  int ret, idx;
1215
0
  unsigned short port = (_port?*_port:0);
1216
1217
0
  if (head) {
1218
    /* we need to check against a specific list */
1219
0
    idx = head - blst_heads;
1220
0
    ret = check_against_rule_list(ip, _pattern, port, _proto, idx);
1221
0
  } else {
1222
    /* if we do not have a head, we check against all enabled */
1223
0
    ret = check_against_blacklist(ip, _pattern, port, _proto);
1224
0
  }
1225
0
  return ret ?1:-1;
1226
0
}
1227
1228
int fixup_blacklist_proto(void** param)
1229
0
{
1230
0
  int proto = PROTO_NONE;
1231
0
  str *s = (str*)*param;
1232
0
  if (s && parse_proto((unsigned char *)s->s, s->len, &proto) < 0)
1233
0
    return E_BAD_PROTO;
1234
1235
0
  *param = (void *)(unsigned long)proto;
1236
0
  return 0;
1237
0
}
1238
1239
int fixup_blacklist_net(void** param)
1240
0
{
1241
0
  str *s = (str*)*param;
1242
0
  str tmp = *s;
1243
0
  struct bl_net_flags *nf = pkg_malloc(sizeof *nf);
1244
0
  if (!nf)
1245
0
    return E_OUT_OF_MEM;
1246
0
  memset(nf, 0, sizeof *nf);
1247
0
  trim(&tmp);
1248
0
  if (tmp.s[0] == '!') {
1249
0
    nf->flags = BLR_APPLY_CONTRARY;
1250
0
    tmp.s++;
1251
0
    tmp.len--;
1252
0
    trim(&tmp);
1253
0
  }
1254
1255
0
  if (parse_ip_net(tmp.s, tmp.len, &nf->ipnet) < 0) {
1256
0
    pkg_free(nf);
1257
0
    return E_BAD_ADDRESS;
1258
0
  }
1259
0
  *param = nf;
1260
0
  return 0;
1261
0
}
1262
1263
int fixup_blacklist_net_free(void** param)
1264
0
{
1265
0
  pkg_free(*param);
1266
0
  return 0;
1267
0
}
1268
1269
int w_add_blacklist_rule(struct sip_msg *msg, struct bl_head *head,
1270
    struct bl_net_flags *nf, int *_port, unsigned short _proto,
1271
    str *_pattern, int *_exp)
1272
0
{
1273
0
  struct bl_rule *list = NULL;
1274
0
  unsigned short port = (_port?*_port:0);
1275
1276
0
  if (head->flags & BL_READONLY_LIST) {
1277
0
    LM_ERR("cannot modify read-only blacklist!\n");
1278
0
    return -1;
1279
0
  }
1280
1281
0
  if (_exp && *_exp && !(head->flags & BL_DO_EXPIRE)) {
1282
0
    LM_ERR("blacklist does not support expiring rules!\n");
1283
0
    return -1;
1284
0
  }
1285
1286
0
  if (add_rule_to_list(&list, &list, &nf->ipnet, _pattern,
1287
0
      port, _proto, nf->flags) != 0) {
1288
0
    LM_ERR("cannot build blacklist rule!\n");
1289
0
    return -1;
1290
0
  }
1291
0
  if (add_list_to_head(head, list, list, 0, (_exp?*_exp:0)) < 0) {
1292
0
    LM_ERR("cannot add blacklist rule!\n");
1293
0
    return -1;
1294
0
  }
1295
0
  return 1;
1296
0
}
1297
1298
int w_del_blacklist_rule(struct sip_msg *msg, struct bl_head *head,
1299
    struct bl_net_flags *nf, int *_port, unsigned short _proto,
1300
    str *_pattern)
1301
0
{
1302
0
  unsigned short port = (_port?*_port:0);
1303
1304
0
  if (head->flags & BL_READONLY_LIST) {
1305
0
    LM_ERR("cannot modify read-only blacklist!\n");
1306
0
    return -1;
1307
0
  }
1308
0
  if (del_rule_from_list(head, &nf->ipnet,
1309
0
      _pattern, port, _proto, nf->flags) != 0)
1310
0
    return -1;
1311
0
  return 1;
1312
0
}