ze-filter  (ze-filter-0.8.0-develop-180218)
ze-dns-urlbl.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-urlbl.h"
28 
29 #include "ze-filter.h"
30 
31 #define URLBL_NONE 0
32 
33 #define URLBL_ONMATCH_CONTINUE 1
34 
35 #define URLBL_RECURSE 2
36 
37 
38 /* ****************************************************************************
39  * *
40  * *
41  **************************************************************************** */
42 bool
43 check_dns_urlbl(name, bl, code, size, recurse)
44  char *name;
45  char *bl;
46  char *code;
47  size_t size;
48  bool recurse;
49 {
50  bool result = FALSE;
51  char domain[256];
52 
53  if (name == NULL || strlen(name) == 0) {
54  ZE_LogMsgError(0, "name : NULL pointer");
55  return FALSE;
56  }
57 
58  if ((bl == NULL) || (strlen(bl) == 0)) {
59  ZE_LogMsgError(0, "urlbl : NULL pointer or empty string");
60  return FALSE;
61  }
62 
63  if ((code != NULL) && (size <= 0)) {
64  ZE_LogMsgError(0, "host size <= 0");
65  return FALSE;
66  }
67 
68  if (name != NULL && zeStrRegex(name, IPV4_ADDR_REGEX, NULL, NULL, TRUE)) {
69  int argc;
70  char *argv[16];
71 
72  char *sip = NULL;
73 
74  DNS_HOSTARR_T a;
75 
76  memset(domain, 0, sizeof (domain));
77  ZE_MessageInfo(11, "IP : %s", name);
78 
79  sip = strdup(name);
80  if (sip == NULL)
81  ZE_MessageError(10, "strdup(%s) error", name);
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  strlcat(domain, ".", sizeof (domain));
91  strlcat(domain, bl, sizeof (domain));
92 
93  ZE_MessageInfo(11, "DOMAIN : %s", domain);
94 
95  FREE(sip);
96 
97  if (dns_get_a(domain + 1, &a) > 0) {
98  int i;
99 
100  for (i = 0; i < a.count; i++) {
101  ZE_MessageInfo(11, " * A : %-16s %s", a.host[i].ip, a.host[i].name);
102  if (code != NULL)
103  strlcpy(code, a.host[i].ip, size);
104 
105  result = TRUE;
106  break;
107  }
108  }
109  dns_free_hostarr(&a);
110  if (result)
111  goto fin;
112  }
113 
114  if (name != NULL && zeStrRegex(name, DOMAINNAME_REGEX, NULL, NULL, TRUE)) {
115  DNS_HOSTARR_T a;
116  char *pname = name;
117 
118  while (pname != NULL && strlen(pname) > 0) {
119  snprintf(domain, sizeof (domain), "%s.%s", pname, bl);
120 
121  if (dns_get_a(domain, &a) > 0) {
122  int i;
123 
124  for (i = 0; i < a.count; i++) {
125  ZE_MessageInfo(12, " * A : %-16s %s", a.host[i].ip, a.host[i].name);
126  if (code != NULL)
127  strlcpy(code, a.host[i].ip, size);
128 
129  result = TRUE;
130  break;
131  }
132  }
133  dns_free_hostarr(&a);
134  if (result || !recurse)
135  goto fin;
136 
137  pname = strchr(pname, '.');
138  if (pname == NULL)
139  break;
140  if (*pname == '.')
141  pname++;
142  if (strchr(pname, '.') == NULL)
143  break;
144  }
145  }
146 
147 fin:
148  return result;
149 }
150 
151 /* ***************************************************************************
152  * *
153  * *
154  *****************************************************************************/
155 #define URLBL_LENX 64
156 
157 #define DIM_URLBL 16
158 
159 
160 typedef struct {
161  bool ok;
162  int nb;
164 } urlblconf_T;
165 
166 
167 /* ***************************************************************************
168  * *
169  * ### ###### ###### ###### #
170  * # # # # # # # #
171  * # # # # # # # #
172  * # ###### ###### ###### #
173  * # # # # # # #
174  * # # # # # # #
175  * ### # # # ###### #######
176  * *
177  *****************************************************************************/
178 
179 static pthread_mutex_t urlbl_mutex = PTHREAD_MUTEX_INITIALIZER;
180 
181 #define URLBL_LOCK() \
182  if (pthread_mutex_lock(&urlbl_mutex) != 0) { \
183  ZE_LogSysError("pthread_mutex_lock(urlbl_mutex)"); \
184  }
185 
186 #define URLBL_UNLOCK() \
187  if (pthread_mutex_unlock(&urlbl_mutex) != 0) { \
188  ZE_LogSysError("pthread_mutex_unlock(urlbl_mutex)"); \
189  }
190 
191 
192 static urlblconf_T urlblCf = { FALSE, 0 };
193 
194 /* ****************************************************************************
195  * *
196  * *
197  **************************************************************************** */
198 
199 #define KEYVALUE "^[a-z0-9_-]+=[^ \t]+"
200 
201 static int
202 read_urlbl_line(v, arg)
203  void *v;
204  void *arg;
205 {
206  char *s = (char *) v;
207  int i, n;
208  int argc;
209  char *argv[32];
210 
211  urlbl_T r;
212 
213  memset(&r, 0, sizeof (r));
214 
215  SKIP_SPACES(s);
216  strlcpy(r.line, s, sizeof (r.line));
217 
218  r.odds = 1.;
219 
220  n = strcspn(s, " \t");
221  zeSafeStrnCpy(r.bl, sizeof (r.bl), s, n);
222  s += n;
223 
224  r.flags |= URLBL_RECURSE;
225  argc = zeStr2Tokens(s, 32, argv, "; ");
226  for (i = 0; i < argc; i++) {
227  char *tag;
228  char *p = argv[i];
229 
230  tag = "code=";
231  if (STRNCASEEQUAL(p, tag, strlen(tag))) {
232  p += strlen(tag);
233 
234  strlcpy(r.code, p, sizeof (r.code));
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 
244  errno = 0;
245  t = strtod(p, NULL);
246  if (errno == 0)
247  r.odds = t;
248  }
249 
250  tag = "score=";
251  if (STRNCASEEQUAL(p, tag, strlen(tag))) {
252  double t;
253  int terrno = 0;
254 
255  p += strlen(tag);
256 
257  errno = 0;
258  t = strtod(p, NULL);
259  if (errno == 0)
260  r.score = t;
261  }
262 
263 
264  tag = "onmatch=";
265  if (STRNCASEEQUAL(p, tag, strlen(tag))) {
266  int argxc;
267  char *argxv[16];
268  char buf[64];
269  int j;
270 
271  p += strlen(tag);
272 
274 
275  strlcpy(buf, p, sizeof (buf));
276  argxc = zeStr2Tokens(buf, 16, argxv, ", ");
277  for (j = 0; j < argxc; j++) {
278  if (STRCASEEQUAL(argxv[j], "stop")) {
280  continue;
281  }
282  if (STRCASEEQUAL(argxv[j], "continue")) {
284  continue;
285  }
286  }
287  }
288 
289  tag = "recurse=";
290  if (STRNCASEEQUAL(p, tag, strlen(tag))) {
291  int argxc;
292  char *argxv[16];
293  char buf[64];
294  int j;
295 
296  p += strlen(tag);
297 
298  strlcpy(buf, p, sizeof (buf));
299  argxc = zeStr2Tokens(buf, 16, argxv, ", ");
300  for (j = 0; j < argxc; j++) {
301  if (STRCASEEQUAL(argxv[j], "no")) {
302  r.flags &= ~(URLBL_RECURSE);
303  continue;
304  }
305  if (STRCASEEQUAL(argxv[j], "yes")) {
306  r.flags |= URLBL_RECURSE;
307  continue;
308  }
309  }
310  }
311  }
312 
313  memset(&r.onmatch, 0, sizeof (r.onmatch));
315  strlcpy(r.onmatch, "continue", sizeof (r.onmatch));
316  else
317  strlcpy(r.onmatch, "stop", sizeof (r.onmatch));
318 
319  if (strlen(r.code) == 0)
320  strlcpy(r.code, "all", sizeof (r.code));
321 
322  if (r.odds <= 0)
323  r.odds = 1;
324 
325  if (urlblCf.nb < DIM_URLBL) {
326  urlblCf.urlbl[urlblCf.nb] = r;
327  urlblCf.nb++;
328  } else
329  ZE_MessageWarning(9, "Too many URLBLs : limit = %d", DIM_URLBL);
330 
331  return 0;
332 }
333 
334 static bool
335 read_it(path, tag)
336  char *path;
337  char *tag;
338 {
339  int r;
340 
341  r = zm_RdFile(path, tag, read_urlbl_line, NULL);
342 
343  return r >= 0;
344 }
345 
346 bool
347 load_urlbl_table(cfdir, fname)
348  char *cfdir;
349  char *fname;
350 {
351  bool result;
352 
353  ASSERT(fname != NULL);
354 
355  URLBL_LOCK();
356 
357  memset(urlblCf.urlbl, 0, sizeof (urlblCf.urlbl));
358  urlblCf.nb = 0;
359 
360  result = read_conf_data_file(cfdir, fname, "ze-tables:dns-urlbl", read_it);
361 
362  urlblCf.ok = result;
363 
364  URLBL_UNLOCK();
365 
366  return result;
367 }
368 
369 /* ****************************************************************************
370  * *
371  * *
372  **************************************************************************** */
373 bool
375 {
376  if (urlblCf.ok)
377  return TRUE;
378 
379  URLBL_LOCK();
380  if (!urlblCf.ok) {
381  memset(urlblCf.urlbl, 0, sizeof (urlblCf.urlbl));
382 
383  urlblCf.nb = 0;
384  urlblCf.ok = TRUE;
385  }
386  URLBL_UNLOCK();
387 
388  return TRUE;
389 }
390 
391 /* ****************************************************************************
392  * *
393  * *
394  **************************************************************************** */
395 void
397 {
398  int i;
399 
400  printf("\n");
401  printf("<DNS-URLBL>\n");
402 
403  for (i = 0; i < urlblCf.nb; i++) {
404  urlbl_T *r;
405 
406  r = &urlblCf.urlbl[i];
407 
408  printf("%-20s odds=%.4f; score=%.3f; code=%s; onmatch=%s; recurse=%s\n",
409  r->bl, r->odds, r->score, r->code, r->onmatch,
410  STRBOOL((r->flags & URLBL_RECURSE) != URLBL_NONE, "yes", "no"));
411  }
412 
413  printf("</DNS-URLBL>\n");
414  printf("\n");
415 }
416 
417 
418 /* ***************************************************************************
419  * *
420  * *
421  *****************************************************************************/
422 static bool
423 get_urlbl_rec(i, urlbl)
424  int i;
425  urlbl_T *urlbl;
426 {
427  bool r = FALSE;
428 
429  URLBL_LOCK();
430  if (urlblCf.ok && i < DIM_URLBL && i < urlblCf.nb) {
431  *urlbl = urlblCf.urlbl[i];
432  r = TRUE;
433  }
434  URLBL_UNLOCK();
435 
436  return r;
437 }
438 
439 uint32_t
440 check_urlbl_table(id, name, urlbl)
441  char *id;
442  char *name;
443  urlbl_T *urlbl;
444 {
445  int i;
446  uint32_t flag = 0;
447  double lodds = 0;
448  double lscore = 0;
449 
450  if (name == NULL || strlen(name) == 0)
451  return 0;
452 
453  for (i = 0; i < DIM_URLBL; i++) {
454  urlbl_T r;
455  char code[64];
456  bool recurse;
457 
458  if (!get_urlbl_rec(i, &r))
459  break;
460 
461  recurse = (r.flags & URLBL_RECURSE) != URLBL_NONE;
462  if (check_dns_urlbl(name, r.bl, code, sizeof (code), recurse)) {
463  /*
464  * check code
465  */
466  if (strlen(r.code) > 0 && !STRCASEEQUAL(r.code, "all")) {
467  int argc;
468  char *argv[16];
469  char buf[256];
470  bool found = FALSE;
471  int j;
472 
473  strlcpy(buf, r.code, sizeof (buf));
474  argc = zeStr2Tokens(buf, 16, argv, ", ");
475  for (j = 0; j < argc; j++) {
476  if (STRCASEEQUAL(code, argv[j])) {
477  found = TRUE;
478  break;
479  }
480  }
481  if (!found)
482  continue;
483  }
484 
485  if (r.odds > 0)
486  lodds += log(r.odds);
487  lscore += r.score;
488 
489  strlcpy(r.code, code, sizeof (r.code));
490  if (urlbl != NULL)
491  *urlbl = r;
492 
493  ZE_MessageInfo(9, "%s URLBL check list=(%s) code=(%s) name=(%s)",
494  id, r.bl, code, STREMPTY(name, "NONAME"));
495 
496  SET_BIT(flag, i);
497 
499  break;
500  }
501  }
502 
503  if (urlbl != NULL) {
504  urlbl->odds = exp(lodds);
505  urlbl->score = lscore;
506  }
507 
508  return flag;
509 }
void dns_free_hostarr(DNS_HOSTARR_T *mx)
Definition: ze-dns-parse.c:89
#define STRBOOL(x, t, f)
Definition: macros.h:87
int zm_RdFile(char *fname, char *tag, RDFILE_F f, void *arg)
Definition: zeRdFile.c:185
char line[256]
Definition: ze-dns-urlbl.h:34
#define URLBL_LOCK()
Definition: ze-dns-urlbl.c:181
#define URLBL_NONE
Definition: ze-dns-urlbl.c:31
void dump_urlbl_table()
Definition: ze-dns-urlbl.c:396
#define ASSERT(a)
Definition: macros.h:27
#define FREE(x)
Definition: macros.h:37
bool check_dns_urlbl(char *name, char *bl, char *code, size_t size, bool recurse)
Definition: ze-dns-urlbl.c:43
#define STRNCASEEQUAL(a, b, n)
Definition: macros.h:75
#define SKIP_SPACES(s)
Definition: macros.h:171
#define FALSE
Definition: macros.h:160
#define strlcpy
Definition: zeString.h:32
#define ZE_LogMsgError(level,...)
Definition: zeSyslog.h:113
char onmatch[20]
Definition: ze-dns-urlbl.h:40
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
#define URLBL_ONMATCH_CONTINUE
Definition: ze-dns-urlbl.c:33
#define URLBL_UNLOCK()
Definition: ze-dns-urlbl.c:186
#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
#define strchr
Definition: ze-sys.h:218
double odds
Definition: ze-dns-urlbl.h:44
#define DOMAINNAME_REGEX
Definition: macros.h:216
DNS_HOST_T host[MAX_HOST]
Definition: ze-dns-parse.h:46
uint16_t flags
Definition: ze-dns-urlbl.h:42
char bl[64]
Definition: ze-dns-urlbl.h:36
uint32_t check_urlbl_table(char *id, char *name, urlbl_T *urlbl)
Definition: ze-dns-urlbl.c:440
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
#define DIM_URLBL
Definition: ze-dns-urlbl.c:157
int zeSafeStrnCpy(char *, size_t, char *, size_t)
Definition: zeStrings.c:136
#define TRUE
Definition: macros.h:157
#define ZE_MessageWarning(level,...)
Definition: zeSyslog.h:92
#define ZE_MessageError(level,...)
Definition: zeSyslog.h:93
char * name
Definition: ze-dns-parse.h:39
#define STREMPTY(x, r)
Definition: macros.h:82
#define URLBL_RECURSE
Definition: ze-dns-urlbl.c:35
char code[64]
Definition: ze-dns-urlbl.h:38
int dns_get_a(char *domain, DNS_HOSTARR_T *a)
Definition: ze-dns-parse.c:153
char * ip
Definition: ze-dns-parse.h:38
#define STRCASEEQUAL(a, b)
Definition: macros.h:72
bool init_urlbl_table()
Definition: ze-dns-urlbl.c:374
urlbl_T urlbl[DIM_URLBL]
Definition: ze-dns-urlbl.c:163
double score
Definition: ze-dns-urlbl.h:45
#define IPV4_ADDR_REGEX
Definition: macros.h:218
long uint32_t
Definition: ze-sys.h:489
bool load_urlbl_table(char *cfdir, char *fname)
Definition: ze-dns-urlbl.c:347
char domain[]