ze-filter  (ze-filter-0.8.0-develop-180218)
ze-dns-iprbwl.c
Go to the documentation of this file.
1 
2 /*
3  *
4  * ze-filter - Mail Server Filter for sendmail
5  *
6  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
7  *
8  * Auteur : Jose Marcio Martins da Cruz
9  * jose.marcio.mc@gmail.org
10  *
11  * Historique :
12  * Creation : janvier 2002
13  *
14  * This program is free software, but with restricted license :
15  *
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * More details about ze-filter license can be found at ze-filter
22  * web site : http://foss.jose-marcio.org
23  */
24 
25 #include <ze-sys.h>
26 
27 #include "ze-dns-iprbwl.h"
28 
29 #include "ze-filter.h"
30 
31 #define RBWL_NONE 0
32 
33 #define RBWL_ONMATCH_CONTINUE 1
34 
35 #define RBWL_CHECK_ADDR 4
36 #define RBWL_CHECK_NAME 8
37 #define RBWL_CHECK_ALL (RBWL_CHECK_ADDR | RBWL_CHECK_NAME)
38 
39 
40 /* ****************************************************************************
41  * *
42  * *
43  **************************************************************************** */
44 bool
45 check_dns_iprbwl(ip, name, rbwl, code, size)
46  char *ip;
47  char *name;
48  char *rbwl;
49  char *code;
50  size_t size;
51 {
52  bool result = FALSE;
53  char domain[256];
54 
55  if ((ip == NULL || strlen(ip) == 0) && (name == NULL || strlen(name) == 0)) {
56  ZE_MessageWarning(10, "rbwl : no IP nor hostname to check");
57  return FALSE;
58  }
59 
60  if ((code != NULL) && (size <= 0)) {
61  ZE_LogMsgError(0, "host size <= 0");
62  return FALSE;
63  }
64 
65  if ((rbwl == NULL) || (strlen(rbwl) == 0)) {
66  ZE_LogMsgError(0, "rbwl : NULL pointer or empty string");
67  return FALSE;
68  }
69 
70  if (ip != NULL && strlen(ip) > 0) {
71  int argc;
72  char *argv[16];
73  char *sip = NULL;
74  DNS_HOSTARR_T a;
75 
76  memset(domain, 0, sizeof (domain));
77  ZE_MessageInfo(11, "IP : %s", ip);
78 
79  sip = strdup(ip);
80  if (sip == NULL)
81  ZE_MessageError(10, "strdup(%s) error", ip);
82 
83  argc = zeStr2Tokens(sip, 16, argv, ".");
84  while (--argc >= 0) {
85  char s[8];
86 
87  snprintf(s, sizeof (s), "%s.", argv[argc]);
88  strlcat(domain, s, sizeof (domain));
89  }
90 
91  strlcat(domain, rbwl, sizeof (domain));
92  ZE_MessageInfo(11, "DOMAIN : %s", domain);
93 
94  FREE(sip);
95 
96  if (dns_get_a(domain + 1, &a) > 0) {
97  int i;
98 
99  for (i = 0; i < a.count; i++) {
100  ZE_MessageInfo(11, " * A : %-16s %s", a.host[i].ip, a.host[i].name);
101  if (code != NULL)
102  strlcpy(code, a.host[i].ip, size);
103 
104  result = TRUE;
105  break;
106  }
107  }
108  dns_free_hostarr(&a);
109  if (result)
110  goto fin;
111  }
112 
113  if (name == NULL || strlen(name) == 0)
114  goto fin;
115 
116  if (strpbrk(name, "[]") != NULL)
117  goto fin;
118 
119  {
120  DNS_HOSTARR_T a;
121 
122  ZE_MessageInfo(11, "NAME : %s", name);
123 
124  snprintf(domain, sizeof (domain), "%s.%s", name, rbwl);
125  ZE_MessageInfo(11, "DOMAIN : %s", domain);
126 
127  if (dns_get_a(domain, &a) > 0) {
128  int i;
129 
130  for (i = 0; i < a.count; i++) {
131  ZE_MessageInfo(11, " * A : %-16s %s", a.host[i].ip, a.host[i].name);
132  if (code != NULL)
133  strlcpy(code, a.host[i].ip, size);
134 
135  result = TRUE;
136  break;
137  }
138  }
139  dns_free_hostarr(&a);
140  if (result)
141  goto fin;
142  }
143 
144 fin:
145  return result;
146 }
147 
148 /* ***************************************************************************
149  * *
150  * *
151  *****************************************************************************/
152 #define RBWL_LENX 64
153 
154 #define DIM_RBWL 16
155 
156 
157 typedef struct {
158  bool ok;
159  int nb;
161 } rbwlconf_T;
162 
163 
164 /* ***************************************************************************
165  * *
166  * ### ###### ###### ###### #
167  * # # # # # # # #
168  * # # # # # # # #
169  * # ###### ###### ###### #
170  * # # # # # # #
171  * # # # # # # #
172  * ### # # # ###### #######
173  * *
174  *****************************************************************************/
175 
176 static pthread_mutex_t rbwl_mutex = PTHREAD_MUTEX_INITIALIZER;
177 
178 #define RBWL_LOCK() \
179  if (pthread_mutex_lock(&rbwl_mutex) != 0) { \
180  ZE_LogSysError("pthread_mutex_lock(rbwl_mutex)"); \
181  }
182 
183 #define RBWL_UNLOCK() \
184  if (pthread_mutex_unlock(&rbwl_mutex) != 0) { \
185  ZE_LogSysError("pthread_mutex_unlock(rbwl_mutex)"); \
186  }
187 
188 
189 static rbwlconf_T ipRbwl = { FALSE, 0 };
190 
191 /* ****************************************************************************
192  * *
193  * *
194  **************************************************************************** */
195 
196 #define KEYVALUE "^[a-z0-9_-]+=[^ \t]+"
197 
198 static int
199 read_iprbwl_line(v, arg)
200  void *v;
201  void *arg;
202 {
203  char *s = (char *) v;
204  int i, n;
205  int argc;
206  char *argv[32];
207  iprbwl_T r;
208 
209  memset(&r, 0, sizeof (r));
210 
211  SKIP_SPACES(s);
212  strlcpy(r.line, s, sizeof (r.line));
213 
214  r.odds = 1.;
215 
216  n = strcspn(s, " \t");
217  zeSafeStrnCpy(r.rbwl, sizeof (r.rbwl), s, n);
218  s += n;
219 
220  argc = zeStr2Tokens(s, 32, argv, "; ");
221  for (i = 0; i < argc; i++) {
222  char *tag;
223  char *p = argv[i];
224 
225  tag = "code=";
226  if (STRNCASEEQUAL(p, tag, strlen(tag))) {
227  p += strlen(tag);
228  strlcpy(r.code, p, sizeof (r.code));
229  }
230 
231  tag = "netclass=";
232  if (STRNCASEEQUAL(p, tag, strlen(tag))) {
233  p += strlen(tag);
234  strlcpy(r.netclass, p, sizeof (r.netclass));
235  }
236 
237  tag = "odds=";
238  if (STRNCASEEQUAL(p, tag, strlen(tag))) {
239  double t;
240  int terrno = 0;
241 
242  p += strlen(tag);
243  errno = 0;
244  t = strtod(p, NULL);
245  if (errno == 0)
246  r.odds = t;
247  }
248 
249  tag = "onmatch=";
250  if (STRNCASEEQUAL(p, tag, strlen(tag))) {
251  int argxc;
252  char *argxv[16];
253  char buf[64];
254  int j;
255 
256  p += strlen(tag);
258  strlcpy(buf, p, sizeof (buf));
259  argxc = zeStr2Tokens(buf, 16, argxv, ", ");
260  for (j = 0; j < argxc; j++) {
261  if (STRCASEEQUAL(argxv[j], "stop")) {
263  continue;
264  }
265  if (STRCASEEQUAL(argxv[j], "continue")) {
267  continue;
268  }
269  }
270  }
271 
272  tag = "checks=";
273  if (STRNCASEEQUAL(p, tag, strlen(tag))) {
274  int argxc;
275  char *argxv[16];
276  char buf[64];
277  int j;
278 
279  p += strlen(tag);
280  strlcpy(buf, p, sizeof (buf));
281  argxc = zeStr2Tokens(buf, 16, argxv, ", ");
282  for (j = 0; j < argxc; j++) {
283  if (STRCASEEQUAL(argxv[j], "ip")) {
284  r.flags |= RBWL_CHECK_ADDR;
285  continue;
286  }
287  if (STRCASEEQUAL(argxv[j], "addr")) {
288  r.flags |= RBWL_CHECK_ADDR;
289  continue;
290  }
291  if (STRCASEEQUAL(argxv[j], "name")) {
292  r.flags |= RBWL_CHECK_NAME;
293  continue;
294  }
295  if (STRCASEEQUAL(argxv[j], "hostname")) {
296  r.flags |= RBWL_CHECK_NAME;
297  continue;
298  }
299  if (STRCASEEQUAL(argxv[j], "all")) {
300  r.flags |= RBWL_CHECK_ALL;
301  continue;
302  }
303  }
304  }
305  }
306 
307  memset(&r.onmatch, 0, sizeof (r.onmatch));
309  strlcpy(r.onmatch, "continue", sizeof (r.onmatch));
310  else
311  strlcpy(r.onmatch, "stop", sizeof (r.onmatch));
312 
313  if ((r.flags & RBWL_CHECK_ALL) == RBWL_NONE)
314  r.flags |= RBWL_CHECK_ADDR;
315  memset(&r.checks, 0, sizeof (r.checks));
316  if ((r.flags & RBWL_CHECK_ADDR) != RBWL_NONE)
317  strlcpy(r.checks, "addr", sizeof (r.checks));
318  if ((r.flags & RBWL_CHECK_NAME) != RBWL_NONE) {
319  if (strlen(r.checks) > 0)
320  strlcat(r.checks, ",", sizeof (r.checks));
321  strlcat(r.checks, "name", sizeof (r.checks));
322  }
323 
324  if (strlen(r.code) == 0)
325  strlcpy(r.code, "all", sizeof (r.code));
326 
327  if (r.odds <= 0)
328  r.odds = 1;
329 
330  if (ipRbwl.nb < DIM_RBWL) {
331  ipRbwl.rbwl[ipRbwl.nb] = r;
332  ipRbwl.nb++;
333  } else
334  ZE_MessageWarning(9, "Too many RBWLs : limit = %d", DIM_RBWL);
335 
336  return 0;
337 }
338 
339 static bool
340 read_it(path, tag)
341  char *path;
342  char *tag;
343 {
344  int r;
345 
346  r = zm_RdFile(path, tag, read_iprbwl_line, NULL);
347 
348  return r >= 0;
349 }
350 
351 bool
352 load_iprbwl_table(cfdir, fname)
353  char *cfdir;
354  char *fname;
355 {
356  bool result;
357 
358  ASSERT(fname != NULL);
359 
360  RBWL_LOCK();
361 
362  memset(ipRbwl.rbwl, 0, sizeof (ipRbwl.rbwl));
363  ipRbwl.nb = 0;
364  result = read_conf_data_file(cfdir, fname, "ze-tables:dns-ip-rbwl", read_it);
365  ipRbwl.ok = result;
366 
367  RBWL_UNLOCK();
368 
369  return result;
370 }
371 
372 /* ****************************************************************************
373  * *
374  * *
375  **************************************************************************** */
376 bool
378 {
379  if (ipRbwl.ok)
380  return TRUE;
381 
382  RBWL_LOCK();
383  if (!ipRbwl.ok) {
384  memset(ipRbwl.rbwl, 0, sizeof (ipRbwl.rbwl));
385  ipRbwl.nb = 0;
386  ipRbwl.ok = TRUE;
387  }
388  RBWL_UNLOCK();
389 
390  return TRUE;
391 }
392 
393 /* ****************************************************************************
394  * *
395  * *
396  **************************************************************************** */
397 void
399 {
400  int i;
401 
402  printf("\n");
403  printf("<DNS-IP-RBWL>\n");
404 
405  for (i = 0; i < ipRbwl.nb; i++) {
406  iprbwl_T *r;
407 
408  r = &ipRbwl.rbwl[i];
409 
410  printf("%-20s netclass=%s; odds=%.4f; code=%s; onmatch=%s; checks=%s\n",
411  r->rbwl, r->netclass, r->odds, r->code, r->onmatch, r->checks);
412  }
413 
414  printf("</DNS-IP-RBWL>\n");
415  printf("\n");
416 }
417 
418 /* ***************************************************************************
419  * *
420  * *
421  *****************************************************************************/
422 static bool
423 get_rbwl_rec(i, rbwl)
424  int i;
425  iprbwl_T *rbwl;
426 {
427  bool r = FALSE;
428 
429  RBWL_LOCK();
430  if (ipRbwl.ok && i < DIM_RBWL && i < ipRbwl.nb) {
431  *rbwl = ipRbwl.rbwl[i];
432  r = TRUE;
433  }
434  RBWL_UNLOCK();
435 
436  return r;
437 }
438 
439 uint32_t
440 check_iprbwl_table(id, ip, name, rbwl)
441  char *id;
442  char *ip;
443  char *name;
444  iprbwl_T *rbwl;
445 {
446  int i;
447  uint32_t flag = 0;
448  double lodds = 0;
449 
450  for (i = 0; i < DIM_RBWL; i++) {
451  iprbwl_T r;
452  char code[64];
453  char *paddr, *pname;
454 
455  if (!get_rbwl_rec(i, &r))
456  break;
457 
458  paddr = pname = NULL;
459 
460  if ((r.flags & RBWL_CHECK_ADDR) != RBWL_NONE)
461  paddr = ip;
462  if ((r.flags & RBWL_CHECK_NAME) != RBWL_NONE)
463  pname = name;
464 
465  ZE_MessageInfo(11, "Checking %s/%s against %s",
466  STRNULL(paddr, "(NULL)"), STRNULL(pname, "(NULL)"), r.rbwl);
467  if (check_dns_iprbwl(paddr, pname, r.rbwl, code, sizeof (code))) {
468  bool found = TRUE;
469 
470  /*
471  * check code
472  */
473  if (strlen(r.code) > 0 && !STRCASEEQUAL(r.code, "all")) {
474  int argc;
475  char *argv[16];
476  char buf[256];
477  int j;
478 
479  found = FALSE;
480 
481  strlcpy(buf, r.code, sizeof (buf));
482  argc = zeStr2Tokens(buf, 16, argv, ", ");
483  for (j = 0; j < argc; j++) {
484  char *p = argv[j];
485 
486  if (STRCASEEQUAL("all", argv[j])) {
487  found = TRUE;
488  break;
489  }
490 
491  if (*p == '!') {
492  p++;
493 
494  if (STRCASEEQUAL(code, p))
495  break;
496  continue;
497  }
498 
499  if (STRCASEEQUAL(code, argv[j])) {
500  found = TRUE;
501  break;
502  }
503  }
504  }
505  if (!found)
506  continue;
507 
508  if (r.odds > 0)
509  lodds += log(r.odds);
510 
511  strlcpy(r.code, code, sizeof (r.code));
512  if (flag == 0 && rbwl != NULL)
513  *rbwl = r;
514 
515  ZE_MessageInfo(10,
516  "%s RBWL check list=(%s) code=(%s) class=(%s) addr=(%s) name=(%s)",
517  id, r.rbwl, code, r.netclass, STREMPTY(ip, "NOIP"),
518  STREMPTY(name, "NONAME"));
519 
520  SET_BIT(flag, i);
521 
523  break;
524  }
525  }
526 
527  if (rbwl != NULL)
528  rbwl->odds = exp(lodds);
529 
530  return flag;
531 }
char rbwl[64]
Definition: ze-dns-iprbwl.h:36
#define RBWL_CHECK_NAME
Definition: ze-dns-iprbwl.c:36
void dns_free_hostarr(DNS_HOSTARR_T *mx)
Definition: ze-dns-parse.c:89
int zm_RdFile(char *fname, char *tag, RDFILE_F f, void *arg)
Definition: zeRdFile.c:185
#define ASSERT(a)
Definition: macros.h:27
char code[64]
Definition: ze-dns-iprbwl.h:38
#define FREE(x)
Definition: macros.h:37
char checks[20]
Definition: ze-dns-iprbwl.h:41
#define STRNULL(x, r)
Definition: macros.h:81
#define STRNCASEEQUAL(a, b, n)
Definition: macros.h:75
#define SKIP_SPACES(s)
Definition: macros.h:171
void dump_iprbwl_table()
bool init_iprbwl_table()
#define RBWL_NONE
Definition: ze-dns-iprbwl.c:31
#define RBWL_ONMATCH_CONTINUE
Definition: ze-dns-iprbwl.c:33
#define FALSE
Definition: macros.h:160
#define strlcpy
Definition: zeString.h:32
#define ZE_LogMsgError(level,...)
Definition: zeSyslog.h:113
#define RBWL_UNLOCK()
#define RBWL_CHECK_ADDR
Definition: ze-dns-iprbwl.c:35
double odds
Definition: ze-dns-iprbwl.h:46
#define SET_BIT(p, i)
Definition: macros.h:166
int zeStr2Tokens(char *, int, char **, char *)
Definition: zeStrings.c:610
bool read_conf_data_file(char *cfdir, char *fname, char *dfile, read_conf_data_file_F func)
#define strlcat
Definition: zeString.h:28
iprbwl_T rbwl[DIM_RBWL]
#define RBWL_LOCK()
char line[256]
Definition: ze-dns-iprbwl.h:34
char netclass[20]
Definition: ze-dns-iprbwl.h:39
DNS_HOST_T host[MAX_HOST]
Definition: ze-dns-parse.h:46
#define DIM_RBWL
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
int zeSafeStrnCpy(char *, size_t, char *, size_t)
Definition: zeStrings.c:136
char onmatch[20]
Definition: ze-dns-iprbwl.h:42
#define TRUE
Definition: macros.h:157
#define ZE_MessageWarning(level,...)
Definition: zeSyslog.h:92
#define RBWL_CHECK_ALL
Definition: ze-dns-iprbwl.c:37
#define ZE_MessageError(level,...)
Definition: zeSyslog.h:93
char * name
Definition: ze-dns-parse.h:39
#define STREMPTY(x, r)
Definition: macros.h:82
bool check_dns_iprbwl(char *ip, char *name, char *rbwl, char *code, size_t size)
Definition: ze-dns-iprbwl.c:45
int dns_get_a(char *domain, DNS_HOSTARR_T *a)
Definition: ze-dns-parse.c:153
char * ip
Definition: ze-dns-parse.h:38
uint16_t flags
Definition: ze-dns-iprbwl.h:44
#define STRCASEEQUAL(a, b)
Definition: macros.h:72
bool load_iprbwl_table(char *cfdir, char *fname)
uint32_t check_iprbwl_table(char *id, char *ip, char *name, iprbwl_T *rbwl)
long uint32_t
Definition: ze-sys.h:489
char domain[]