ze-filter  (ze-filter-0.8.0-develop-180218)
ze-grey.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 : Fri Jan 21 14:26:51 CET 2005
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 #include <libze.h>
27 #include <ze-filter.h>
28 #include <ze-grey.h>
29 #include <ze-log-grey.h>
30 
31 /* ****************************************************************************
32  * *
33  * *
34  **************************************************************************** */
35 #define BF_SZ 512
36 
37 #ifndef DT_GREY_SLEEP
38 #define DT_GREY_SLEEP 10
39 #endif /* DT_GREY_SLEEP */
40 
41 #define DT_GREY_INTERVAL (6 HOURS)
42 
43 #ifndef MIN_CNT_PER_DOMAIN
44 #define MIN_CNT_PER_DOMAIN 5
45 #endif /* MIN_CNT_PER_DOMAIN */
46 
47 #ifndef GREY_TP_MIN_NORM
48 #define GREY_TP_MIN_NORM 10 MINUTES
49 #endif /* GREY_TP_MIN_NORM */
50 #ifndef GREY_TP_MIN_NULL
51 #define GREY_TP_MIN_NULL 10 MINUTES
52 #endif /* GREY_TP_MIN_NULL */
53 #ifndef GREY_TP_MAX_NORM
54 #define GREY_TP_MAX_NORM 3 DAYS
55 #endif /* GREY_TP_MAX_NORM */
56 #ifndef GREY_TP_MAX_NULL
57 #define GREY_TP_MAX_NULL 4 HOURS
58 #endif /* GREY_TP_MAX_NULL */
59 
60 #ifndef GREY_TV_MAX
61 #define GREY_TV_MAX 7 DAYS
62 #endif /* GREY_TV_MAX */
63 #ifndef GREY_TW_MAX
64 #define GREY_TW_MAX 21 DAYS
65 #endif /* GREY_TW_MAX */
66 #ifndef GREY_TB_MAX
67 #define GREY_TB_MAX 7 DAYS
68 #endif /* GREY_TB_MAX */
69 
70 #ifndef T_EXPIRE_BAD_MIN
71 #define T_EXPIRE_BAD_MIN 6 HOURS
72 #endif /* T_EXPIRE_BAD_MIN */
73 #ifndef T_EXPIRE_PENDING_BAD_MAX
74 #define T_EXPIRE_PENDING_BAD_MAX 24 HOURS
75 #endif /* T_EXPIRE_PENDING_BAD_MAX */
76 #ifndef T_EXPIRE_VALID_BAD_MAX
77 #define T_EXPIRE_VALID_BAD_MAX 5 DAYS
78 #endif /* T_EXPIRE_VALID_BAD_MAX */
79 
80 static bool grey_compat_domain_check = TRUE;
81 
82 static bool rdonly = FALSE;
83 
84 static int grey_mode = GREY_STANDALONE;
85 
86 static time_t grey_tp_min_norm = GREY_TP_MIN_NORM;
87 static time_t grey_tp_min_null = GREY_TP_MIN_NULL;
88 static time_t grey_tp_min_no_match = GREY_TP_MIN_NULL;
89 
90 static time_t grey_tp_max_norm = GREY_TP_MAX_NORM;
91 static time_t grey_tp_max_null = GREY_TP_MAX_NULL;
92 
93 static time_t grey_tv_max = GREY_TV_MAX;
94 static time_t grey_tw_max = GREY_TW_MAX;
95 static time_t grey_tb_max = GREY_TB_MAX;
96 
97 static int max_pending_normal = 1000;
98 static int max_pending_null = 100;
99 
100 static time_t dt_grey_cleanup = 2 MINUTES;
101 
102 static int select_ip = GREY_ADDR_NET;
103 static int select_from = GREY_EMAIL_HOST;
104 static int select_rcpt = GREY_EMAIL_FULL;
105 
107 
109  bool ok;
110 
112  int nbp;
114  int nbv;
116  int nbw;
118  int nbb;
119 
120 #if 0
121  bool compat_domain_check;
122 
123  bool rdonly;
124 
125  int mode;
126 
127  time_t tp_min_norm;
128  time_t tp_min_null;
129  time_t tp_min_no_match;
130 
131  time_t tp_max_norm;
132  time_t tp_max_null;
133 
134  time_t tv_max;
135  time_t tw_max;
136  time_t tb_max;
137 
138  int max_pending_normal;
139  int max_pending_null;
140 
141  time_t dt_cleanup;
142 
143  int select_ip;
144  int select_from;
145  int select_rcpt;
146 #endif
147 };
148 
149 static grey_filter_T gdata = {
150  TRUE,
151 
152  ZEDB_INITIALIZER, 0,
153  ZEDB_INITIALIZER, 0,
154  ZEDB_INITIALIZER, 0,
155 
156 #if 0
157  /*
158  * grey_compat_domain_check
159  */
160  TRUE,
161 
162  /*
163  * rdonly
164  */
165  FALSE,
166 
167  /*
168  * grey_mode
169  */
171 
172  /*
173  * grey_tp_min_norm
174  */
176  /*
177  * grey_tp_min_null
178  */
180  /*
181  * grey_tp_min_no_match
182  */
184 
185  /*
186  * grey_tp_max_norm
187  */
189  /*
190  * grey_tp_max_null
191  */
193 
194  /*
195  * grey_tv_max
196  */
197  GREY_TV_MAX,
198  /*
199  * grey_tw_max
200  */
201  GREY_TW_MAX,
202  /*
203  * grey_tb_max
204  */
205  GREY_TB_MAX,
206 
207  /*
208  * max_pending_normal
209  */
210  1000,
211  /*
212  * max_pending_null
213  */
214  100,
215 
216  /*
217  * dt_grey_cleanup
218  */
219  2 MINUTES,
220 
221  /*
222  * select_ip
223  */
225  /*
226  * select_from
227  */
229  /*
230  * select_rcpt
231  */
233 #endif
234 };
235 
236 
237 /* functions */
238 static char *grey_key(char *, char *, char *, int, int, int);
239 
240 #if 0
241 static char *grey_key_pending(char *, char *, char *, int, int, int);
242 static char *grey_key_valid(char *, char *, char *, int, int, int);
243 static char *grey_key_black(char *, char *, char *, int, int, int);
244 #endif
245 static char *grey_key_white(char *, char *);
246 
247 static int grey_count_pending(char *);
248 
249 
250 static bool db_grey_open(char *, bool);
251 static bool db_grey_reopen();
252 static bool db_grey_close();
253 static bool db_grey_flush();
254 
255 static bool grey_add_rec(ZEDB_T *, char *, void *, size_t);
256 static bool grey_get_rec(ZEDB_T *, char *, void *, size_t);
257 static bool grey_del_rec(ZEDB_T *, char *);
258 
259 static bool grey_cursor_open(ZEDB_T *, bool);
260 static bool grey_cursor_get_first(ZEDB_T *, char *, size_t, void *,
261  size_t);
262 static bool grey_cursor_get_next(ZEDB_T *, char *, size_t, void *,
263  size_t);
264 static bool grey_cursor_close(ZEDB_T *);
265 
266 typedef struct expire_st_T expire_st_T;
267 
268 static bool grey_database_expire(ZEDB_T *, expire_st_T *, time_t,
269  time_t, int);
270 
271 void grey_launch_thread();
272 
273 static pthread_mutex_t grey_crit = PTHREAD_MUTEX_INITIALIZER;
274 
275 #define GREY_CRIT_LOCK() MUTEX_LOCK(&grey_crit)
276 #define GREY_CRIT_UNLOCK() MUTEX_UNLOCK(&grey_crit)
277 
278 #ifndef DBG_LEVEL
279 #define DBG_LEVEL 12
280 #endif
281 
282 typedef struct tuple_T tuple_T;
283 
284 struct tuple_T {
285  char *ip;
286  char *from;
287  char *to;
288  char *hostname;
289  time_t date;
290  char *key;
291 };
292 
293 #if 0
294 static bool tuple_str2rec(tuple_T *, char *);
295 static bool tuple_rec2str(char *, tuple_T *, size_t);
296 #endif
297 typedef struct grey_entry_T grey_entry_T;
298 
299 struct grey_entry_T {
300  time_t date_init;
301  time_t date_updt;
302 
303  char ip[256];
304  char hostname[256];
305  char from[256];
306  char rcpt[256];
307 
308  /*
309  * value
310  */
311  char vip[256];
312  char vhostname[256];
313  char vfrom[256];
314  char vrcpt[256];
315  int count;
316  bool resolve;
317 
318  /*
319  * key
320  */
321 #if 0
322  char kip[256];
323  char kfrom[256];
324  char krcpt[256];
325 #endif
326 };
327 
328 #define GREY_ENTRY_INITIALIZER {0, 0, NULL, NULL, NULL, NULL, \
329  NULL, NULL, NULL, NULL, 0, FALSE, NULL, NULL, NULL}
330 
331 static char *grey_separator(char *s);
332 static bool grey_value_str2entry(grey_entry_T *, char *);
333 static bool grey_value_entry2str(char *, grey_entry_T *, size_t);
334 
335 #if 0
336 static bool grey_key_str2entry(grey_entry_T *, char *);
337 static bool grey_key_entry2str(char *, grey_entry_T *, size_t);
338 #endif
339 static void grey_entry_free(grey_entry_T *);
340 
341 #define ISNULLSENDER(x) (((x) == NULL) || \
342  (strstr((x), "<>") != NULL) || \
343  (strlen((x)) == 0) || \
344  (strcasecmp((x), "nullsender") == 0) || \
345  (strncasecmp((x), "postmaster", 10) == 0) || \
346  (strncasecmp((x), "mailer-daemon", 13) == 0))
347 
348 static bool compatible_domainnames(char *da, char *db);
349 
350 /* ****************************************************************************
351  * *
352  * *
353  **************************************************************************** */
354 bool
355 grey_set_tuples(ip, from, to)
356  char *ip;
357  char *from;
358  char *to;
359 {
360  if (ip == NULL && from == NULL && to == NULL)
361  return FALSE;
362 
363  if (ip != NULL) {
364  if (strcasecmp(ip, "NONE") == 0)
365  select_ip = GREY_ADDR_NONE;
366  if (strcasecmp(ip, "FULL") == 0)
367  select_ip = GREY_ADDR_FULL;
368  if (strcasecmp(ip, "NET") == 0)
369  select_ip = GREY_ADDR_NET;
370  }
371  if (from != NULL) {
372  if (strcasecmp(from, "NONE") == 0)
373  select_from = GREY_EMAIL_NONE;
374  if (strcasecmp(from, "FULL") == 0)
375  select_from = GREY_EMAIL_FULL;
376  if (strcasecmp(from, "USER") == 0)
377  select_from = GREY_EMAIL_USER;
378  if (strcasecmp(from, "HOST") == 0)
379  select_from = GREY_EMAIL_HOST;
380  }
381  if (to != NULL) {
382  if (strcasecmp(to, "NONE") == 0)
383  select_rcpt = GREY_EMAIL_NONE;
384  if (strcasecmp(to, "FULL") == 0)
385  select_rcpt = GREY_EMAIL_FULL;
386  if (strcasecmp(to, "USER") == 0)
387  select_rcpt = GREY_EMAIL_USER;
388  if (strcasecmp(to, "HOST") == 0)
389  select_rcpt = GREY_EMAIL_HOST;
390  }
391  return TRUE;
392 }
393 
394 /* ****************************************************************************
395  * *
396  * *
397  **************************************************************************** */
398 bool
399 grey_set_delays(tp_min_norm, tp_max_norm, tp_min_null, tp_max_null)
400  time_t tp_min_norm;
401  time_t tp_max_norm;
402  time_t tp_min_null;
403  time_t tp_max_null;
404 {
405  if (tp_min_norm >= 1 MINUTES)
406  grey_tp_min_norm = tp_min_norm;
407  if (tp_max_norm >= 1 MINUTES)
408  grey_tp_max_norm = MAX(tp_max_norm, tp_min_norm);
409  if (tp_min_null >= 1 MINUTES)
410  grey_tp_min_null = tp_min_null;
411  if (tp_max_null >= 1 MINUTES)
412  grey_tp_max_null = MAX(tp_min_null, tp_max_null);
413 
414  return TRUE;
415 }
416 
417 /* ****************************************************************************
418  * *
419  * *
420  **************************************************************************** */
421 bool
422 grey_set_lifetime(tv, tw, tb)
423  time_t tv;
424  time_t tw;
425  time_t tb;
426 {
427  if (tv >= 1 MINUTES)
428  grey_tv_max = tv;
429  if (tw >= 1 MINUTES)
430  grey_tw_max = tw;
431  if (tb >= 1 MINUTES)
432  grey_tb_max = tb;
433 
434  return TRUE;
435 }
436 
437 /* ****************************************************************************
438  * *
439  * *
440  **************************************************************************** */
441 bool
442 grey_set_max_pending(nbnormal, nbnull)
443  int nbnormal;
444  int nbnull;
445 {
446  if (nbnormal > 0)
447  max_pending_normal = nbnormal;
448  if (nbnull > 0)
449  max_pending_null = nbnull;
450 
451  return TRUE;
452 }
453 
454 /* ****************************************************************************
455  * *
456  * *
457  **************************************************************************** */
458 bool
460  time_t tclean;
461 {
462  if (tclean >= 1 MINUTES)
463  dt_grey_cleanup = tclean;
464 
465  return TRUE;
466 }
467 
468 /* ****************************************************************************
469  * *
470  * *
471  **************************************************************************** */
472 void
474  bool enable;
475 {
476  grey_compat_domain_check = enable;
477 }
478 
479 /* ****************************************************************************
480  * *
481  * *
482  **************************************************************************** */
483 
484 /*
485  ### #### # #####
486  # # # # #
487  # #### # #
488  ### # # # #
489 */
490 int
491 grey_check(kAddr, kFrom, kRcpt, kName, new, can_validate)
492  char *kAddr;
493  char *kFrom;
494  char *kRcpt;
495  char *kName;
496  bool *new;
497  bool can_validate;
498 {
499  int result = GREY_WAIT;
500  time_t now;
501  char *key = NULL;
502  char value[256];
503  bool null_sender = FALSE;
504  char *ip, *from, *rcpt, *hostname;
505  bool domain_ok = TRUE;
506 
507  grey_entry_T entry;
508 
509  char ipbuf[128];
510 
511  memset(&entry, 0, sizeof (entry));
512 
513  if (new != NULL)
514  *new = FALSE;
515 
516  ip = from = rcpt = hostname = NULL;
517 
518  /*
519  * normalize from and rcpt addresses
520  */
521  kAddr = STRNULL(kAddr, "-");
522 
523  if (ISNULLSENDER(kFrom))
524  kFrom = "nullsender";
525 
526  kRcpt = STRNULL(kRcpt, "");
527  kName = STRNULL(kName, kAddr);
528 
529  ip = kAddr;
530  if (zeStrRegex(ip, IPV6_ADDR_REGEX, NULL, NULL, TRUE)) {
531  ipv6_T ipv6;
532 
533  if (ipv6_str2rec(&ipv6, ip)) {
534  ipv6_prefix_str(&ipv6, ipbuf, sizeof (ipbuf), 64);
535  ip = ipbuf;
536  }
537  }
538 
539  if ((from = strdup(kFrom)) != NULL)
540  (void) extract_email_address(from, kFrom, strlen(kFrom) + 1);
541  else
542  ZE_LogSysError("Error malloc strdup(%s)", kFrom);
543 
544  ZE_MessageInfo(19, "from - %s - %s", kFrom, from);
545 
546  if ((rcpt = strdup(kRcpt)) != NULL)
547  (void) extract_email_address(rcpt, kRcpt, strlen(kRcpt) + 1);
548  else
549  ZE_LogSysError("Error malloc strdup(%s)", kRcpt);
550 
551  if (from == NULL || rcpt == NULL)
552  goto end;
553 
554  hostname = kName;
555 
556  now = time(NULL);
557 
558  ZE_LogMsgInfo(DBG_LEVEL, "IP : %s", ip);
559 
560  /*
561  * check static whitelist database
562  */
563  {
564 
565  }
566 
567  /*
568  * check dynamic whitelist database
569  */
570  GREY_CRIT_LOCK();
571  {
572  char buf_from[BF_SZ], *pf;
573  bool nullsender = FALSE;
574 
575  pf = buf_from;
576  memset(buf_from, 0, sizeof (buf_from));
577 
578  nullsender = ISNULLSENDER(from);
579  if (!nullsender) {
580  (void) extract_email_address(buf_from, from, sizeof (buf_from));
581  pf = buf_from;
582 
583  while (result != GREY_OK && pf != NULL && strlen(pf) > 0) {
584  char *p;
585 
586  key = grey_key_white(ip, pf);
587  if (key != NULL) {
588  if (grey_get_rec(&gdata.gdbw, key, value, sizeof (value))) {
589  grey_entry_free(&entry);
590  (void) grey_value_str2entry(&entry, value);
591 
592  ZE_MessageInfo(19, "date_updt/now : %ld/%ld", entry.date_updt, now);
593  if (entry.date_updt + DT_GREY_INTERVAL < now) {
594  entry.date_updt = now;
595  entry.count++;
596  (void) grey_value_entry2str(value, &entry, sizeof (value));
597  (void) grey_add_rec(&gdata.gdbw, key, value, strlen(value));
598  if (new != NULL)
599  *new = TRUE;
600  }
601  result = GREY_OK;
602  }
603  } else
604  ZE_LogSysError("grey_key_white error...");
605 
606  FREE(key);
607 
608  if ((p = strchr(pf, '.')) != NULL)
609  pf = ++p;
610  else
611  pf = NULL;
612  }
613  }
614  }
615 
616  if (result != GREY_WAIT)
617  goto endlock;
618 
619  key = grey_key(ip, from, rcpt, select_ip, select_from, select_rcpt);
620 
621  if (key == NULL) {
622  result = GREY_ERROR;
623  goto endlock;
624  }
625 
626  ZE_MessageInfo(DBG_LEVEL, "KEY : %s", key);
627 
628  /*
629  * check against valid entries database
630  */
631  if (grey_get_rec(&gdata.gdbv, key, value, sizeof (value))) {
632  grey_entry_free(&entry);
633  (void) grey_value_str2entry(&entry, value);
634 
635  /*
636  * XXX JOE - check if the entry is already expired
637  */
638 
639  ZE_MessageInfo(19, "date_updt/now : %ld/%ld", entry.date_updt, now);
640  if (entry.date_updt + DT_GREY_INTERVAL < now) {
641  entry.date_updt = now;
642  entry.count++;
643  (void) grey_value_entry2str(value, &entry, sizeof (value));
644  (void) grey_add_rec(&gdata.gdbv, key, value, strlen(value));
645  if (new != NULL)
646  *new = TRUE;
647  }
648 
649  result = GREY_OK;
650  }
651 
652  if (result == GREY_OK)
653  goto endlock;
654 
655  null_sender = ISNULLSENDER(from);
656 
657  /*
658  * check against pending entries database
659  */
660  memset(value, 0, sizeof (value));
661  if (grey_get_rec(&gdata.gdbp, key, value, sizeof (value))) {
662  time_t last = 0;
663  time_t dt_min, dt_max;
664 
665  grey_entry_free(&entry);
666  (void) grey_value_str2entry(&entry, value);
667  last = entry.date_init;
668 
669  if (last == 0) {
670  char tbuf[256];
671  static int nb = 0;
672 
673  if (nb++ < 1000) {
674  snprintf(tbuf, sizeof (tbuf), "%ld:%ld:%s:%s:%s:%s:%d:%s",
675  entry.date_init,
676  entry.date_updt,
677  entry.ip,
678  entry.hostname,
679  STRBOOL(ISNULLSENDER(entry.from), "nullsender", entry.from),
680  "FLAGS", entry.count < 1 ? 1 : entry.count, "NULL");
681  ZE_MessageInfo(9, "ENTRY - Decoding error");
682  ZE_MessageInfo(9, "ENTRY - KEY : %s", key);
683  ZE_MessageInfo(9, "ENTRY - VALUE IN : %s", value);
684  ZE_MessageInfo(9, "ENTRY - VALUE OUT : %s", tbuf);
685  }
686  }
687 
688  /*
689  * XXX create new value - if shall update entry
690  */
691  entry.date_init = entry.date_updt = now;
692 
693  if (null_sender) {
694  dt_min = grey_tp_min_null;
695  dt_max = grey_tp_max_null;
696  } else {
697  dt_min = grey_tp_min_norm;
698  dt_max = grey_tp_max_norm;
699 
700 #if 1
701  if (hostname != NULL)
702  domain_ok = compatible_domainnames(from, hostname);
703  if (!domain_ok) {
704  dt_min *= 2;
705  dt_min = MAX(dt_min, 15 MINUTES);
706  }
707 #endif
708  }
709 
710  /*
711  * Check :
712  * ** -> Compatible domains - add penalty to dt_min
713  * ** -> spammer -> add penalty to dt_min
714  */
715 
716  /*
717  * not yet...
718  */
719  if (last + dt_min > now) {
720  result = GREY_WAIT;
721  (void) grey_entry_free(&entry);
722  goto endlock;
723  }
724 
725  /*
726  * OK - let's remove pending record
727  */
728  (void) grey_del_rec(&gdata.gdbp, key);
729 
730  /*
731  * not too late
732  */
733  if (last == 0 || last + dt_max > now) {
734  /*
735  * don't validate null_senders
736  */
737 
738  if (!null_sender && can_validate) {
739  entry.date_init = entry.date_updt = now;
740  (void) grey_value_entry2str(value, &entry, sizeof (value));
741  (void) grey_add_rec(&gdata.gdbv, key, value, strlen(value));
742  }
743  if (new != NULL)
744  *new = TRUE;
745 
746  result = GREY_OK;
747 
748  goto endlock;
749  }
750 
751  result = GREY_WAIT;
752  }
753 
754  {
755  int max_pending;
756  int count = 0;
757 
758  if (null_sender)
759  max_pending = max_pending_null;
760  else
761  max_pending = max_pending_normal;
762 
763  if (max_pending > 0) {
764  count = grey_count_pending(ip);
765  ZE_MessageInfo(DBG_LEVEL, "COUNT KEY : %-16s %d", key, count);
766  }
767 
768  if (max_pending == 0 || count < max_pending) {
769  bool r = FALSE;
770 
771  /*
772  * add entry to pending database
773  */
774  ZE_MessageInfo(DBG_LEVEL, "ADDING KEY : %s %s %s", key, value,
775  STRBOOL(r, "OK", "KO"));
776 
777  grey_entry_free(&entry);
778  entry.date_init = entry.date_updt = now;
779  strlcpy(entry.ip, ip, sizeof (entry.ip));
780  strlcpy(entry.hostname, hostname, sizeof (entry.hostname));
781  strlcpy(entry.from, from, sizeof (entry.from));
782  entry.count = 1;
783 
784  /*
785  * XXX JOE define FLAGS - compatible_domains
786  */
787 
788  (void) grey_value_entry2str(value, &entry, sizeof (value));
789 
790  r = grey_add_rec(&gdata.gdbp, key, value, strlen(value));
791 
792  if (new != NULL)
793  *new = TRUE;
794  }
795  result = GREY_WAIT;
796 
797  goto endlock;
798  }
799 
800 endlock:
802 
803 end:
804  FREE(key);
805  FREE(from);
806  FREE(rcpt);
807 
808  grey_entry_free(&entry);
809 
810  return result;
811 }
812 
813 /* ****************************************************************************
814  * *
815  * *
816  **************************************************************************** */
817 
818 /*
819  ### #### # #####
820  # # # # #
821  # #### # #
822  ### # # # #
823 */
824 int
825 grey_validate(kAddr, kFrom, kRcpt, kName)
826  char *kAddr;
827  char *kFrom;
828  char *kRcpt;
829  char *kName;
830 {
831  int result = GREY_OK;
832  time_t now;
833  char *vkey = NULL;
834  char value[256];
835  char *ip, *from, *rcpt, *hostname;
836 
837  char ipbuf[128];
838 
839  vkey = ip = from = rcpt = hostname = NULL;
840 
841  /*
842  * normalize from and rcpt addresses
843  */
844  {
845  kAddr = STRNULL(kAddr, "-");
846  if (ISNULLSENDER(kFrom)) {
847  kFrom = "nullsender";
848  goto end;
849  }
850  kRcpt = STRNULL(kRcpt, "");
851  kName = STRNULL(kName, kAddr);
852  ip = from = rcpt = hostname = NULL;
853 
854  ip = kAddr;
855  if (zeStrRegex(ip, IPV6_ADDR_REGEX, NULL, NULL, TRUE)) {
856  ipv6_T ipv6;
857 
858  if (ipv6_str2rec(&ipv6, ip)) {
859  ipv6_prefix_str(&ipv6, ipbuf, sizeof (ipbuf), 64);
860  ip = ipbuf;
861  }
862  }
863 
864  from = strdup(kFrom);
865  (void) extract_email_address(from, kFrom, strlen(kFrom) + 1);
866 
867  rcpt = strdup(kRcpt);
868  (void) extract_email_address(rcpt, kRcpt, strlen(kRcpt) + 1);
869 
870  hostname = kName;
871  }
872 
873  if (from == NULL || strlen(from) == 0) {
874  result = GREY_ERROR;
875  goto end;
876  }
877  if (rcpt == NULL || strlen(rcpt) == 0) {
878  result = GREY_ERROR;
879  goto end;
880  }
881 
882  ZE_LogMsgInfo(DBG_LEVEL, "IP : %s", ip);
883 
884  now = time(NULL);
885 
886  vkey = grey_key(ip, from, rcpt, select_ip, select_from, select_rcpt);
887  if (vkey == NULL) {
888  result = GREY_ERROR;
889  goto end;
890  }
891 
892  ZE_MessageInfo(DBG_LEVEL, "KEY : %s", vkey);
893 
894  GREY_CRIT_LOCK();
895 
896  /*
897  * refresh whitelisted entries, if there are any
898  */
899 #if 1
900  {
901  char *pf = NULL;
902  grey_entry_T entry;
903 
904  memset(&entry, 0, sizeof (entry));
905 
906  pf = from;
907  while (pf != NULL && strlen(pf) > 0) {
908  char *p;
909  char *wkey = NULL;
910 
911  wkey = grey_key_white(ip, pf);
912  if (wkey != NULL) {
913  if (grey_get_rec(&gdata.gdbw, wkey, value, sizeof (value))) {
914  grey_entry_free(&entry);
915  (void) grey_value_str2entry(&entry, value);
916 
917  ZE_MessageInfo(19, "date_updt/now : %ld/%ld", entry.date_updt, now);
918  if (entry.date_updt + DT_GREY_INTERVAL < now) {
919  entry.date_updt = now;
920  entry.count++;
921  (void) grey_value_entry2str(value, &entry, sizeof (value));
922  (void) grey_add_rec(&gdata.gdbw, wkey, value, strlen(value));
923  }
924  }
925  } else
926  ZE_LogSysError("grey_key_white error...");
927 
928  FREE(wkey);
929 
930  if ((p = strchr(pf, '.')) != NULL)
931  pf = ++p;
932  else
933  pf = NULL;
934  }
935  }
936 #endif
937 
938  /*
939  * refresh/create valid entry
940  */
941 #if 1
942  {
943  grey_entry_T entry;
944 
945  memset(&entry, 0, sizeof (entry));
946 
947  if (grey_get_rec(&gdata.gdbv, vkey, value, sizeof (value))) {
948  grey_entry_free(&entry);
949  (void) grey_value_str2entry(&entry, value);
950 
951  if (entry.date_updt + DT_GREY_INTERVAL < now) {
952  entry.date_updt = now;
953  entry.count++;
954 
955  (void) grey_value_entry2str(value, &entry, sizeof (value));
956  (void) grey_entry_free(&entry);
957  (void) grey_add_rec(&gdata.gdbv, vkey, value, strlen(value));
958  }
959  } else {
960  entry.date_init = entry.date_updt = now;
961  strlcpy(entry.ip, ip, sizeof (entry.ip));
962  strlcpy(entry.hostname, hostname, sizeof (entry.hostname));
963  strlcpy(entry.from, from, sizeof (entry.from));
964  entry.count = 1;
965 
966  (void) grey_value_entry2str(value, &entry, sizeof (value));
967  (void) grey_entry_free(&entry);
968  (void) grey_add_rec(&gdata.gdbv, vkey, value, strlen(value));
969  }
970  }
971 #else
972  {
973  grey_entry_T entry;
974 
975  memset(&entry, 0, sizeof (entry));
976 
977  entry.date_init = entry.date_updt = now;
978  strlcpy(entry.ip, ip, sizeof (entry.ip));
979  strlcpy(entry.hostname, hostname, sizeof (entry.hostname));
980  strlcpy(entry.from, from, sizeof (entry.from));
981  entry.count = 1;
982 
983  /*
984  * XXX JOE define FLAGS - compatible_domains
985  */
986 
987  (void) grey_value_entry2str(value, &entry, sizeof (value));
988  (void) grey_entry_free(&entry);
989 
990  (void) grey_add_rec(&gdata.gdbv, vkey, value, strlen(value));
991  }
992 #endif
993 
994  /*
995  * check against pending entries database
996  */
997  if (grey_get_rec(&gdata.gdbp, vkey, value, sizeof (value))) {
998  /*
999  * OK - let's remove pending record
1000  */
1001  (void) grey_del_rec(&gdata.gdbp, vkey);
1002  }
1003 
1004  GREY_CRIT_UNLOCK();
1005 
1006 end:
1007  FREE(vkey);
1008  FREE(from);
1009  FREE(rcpt);
1010 
1011  return result;
1012 }
1013 
1014 /* ****************************************************************************
1015  * *
1016  * *
1017  **************************************************************************** */
1018 bool
1020  char *which;
1021  char *key;
1022 {
1023  return TRUE;
1024 }
1025 
1026 /* ****************************************************************************
1027  * *
1028  * *
1029  **************************************************************************** */
1030 bool
1032  char *which;
1033  char *fname;
1034 {
1035  return TRUE;
1036 }
1037 
1038 /* ****************************************************************************
1039  * *
1040  * *
1041  **************************************************************************** */
1042 
1043 static char *
1044 grey_key(ip, from, rcpt, ipFlags, fromFlags, rcptFlags)
1045  char *ip;
1046  char *from;
1047  char *rcpt;
1048  int ipFlags;
1049  int fromFlags;
1050  int rcptFlags;
1051 {
1052  char *p = NULL;
1053  size_t sz = 0;
1054 
1055  ip = STRNULL(ip, "-");
1056  from = STRNULL(from, "nullsender");
1057  rcpt = STRNULL(rcpt, "-");
1058 
1059  if (zeStrRegex(from, "<>", NULL, NULL, TRUE))
1060  from = "<>";
1061 
1062  sz = 3 * BF_SZ + 3;
1063 
1064  if ((p = malloc(sz)) == NULL) {
1065  ZE_LogSysError("malloc(%ld)", (long) sz);
1066  return NULL;
1067  }
1068 
1069  {
1070  char buf_from[BF_SZ], *pf = buf_from;
1071  char buf_rcpt[BF_SZ], *pt = buf_rcpt;
1072  char buf_ip[BF_SZ], *pi = buf_ip;
1073  char *q;
1074 
1075  bool nullsender = FALSE;
1076 
1077  memset(buf_from, 0, sizeof (buf_from));
1078  memset(buf_rcpt, 0, sizeof (buf_rcpt));
1079  memset(buf_ip, 0, sizeof (buf_ip));
1080 
1081  nullsender = ISNULLSENDER(from);
1082 
1083  if (zeStrRegex(ip, IPV6_ADDR_REGEX, NULL, NULL, TRUE)) {
1084  ipv6_T ipv6;
1085 
1086  if (ipv6_str2rec(&ipv6, ip))
1087  ipv6_prefix_str(&ipv6, buf_ip, sizeof (buf_ip), 56);
1088  } else
1089  strlcpy(buf_ip, ip, sizeof (buf_ip));
1090 
1091  (void) extract_email_address(buf_from, from, sizeof (buf_from));
1092  (void) extract_email_address(buf_rcpt, rcpt, sizeof (buf_rcpt));
1093 
1094  if (fromFlags != GREY_EMAIL_NONE && nullsender)
1095  snprintf(buf_from, sizeof (buf_from), "nullsender");
1096 
1097  ZE_MessageInfo(DBG_LEVEL, "GREY FLAGS : %d %d %d", ipFlags, fromFlags,
1098  rcptFlags);
1099 
1100  switch (ipFlags) {
1101  case GREY_ADDR_NONE:
1102  *pf = '\0';
1103  break;
1104  case GREY_ADDR_FULL:
1105  break;
1106  case GREY_ADDR_NET:
1107  /*
1108  * IPV6
1109  */
1110  if ((q = strrchr(buf_ip, '.')) != NULL)
1111  *q = '\0';
1112  break;
1113  }
1114 
1115  switch (fromFlags) {
1116  case GREY_EMAIL_NONE:
1117  *pf = '\0';
1118  break;
1119  case GREY_EMAIL_FULL:
1120  break;
1121  case GREY_EMAIL_USER:
1122  if ((q = strchr(buf_from, '@')) != NULL)
1123  *q = '\0';
1124  break;
1125  case GREY_EMAIL_HOST:
1126  if ((q = strchr(buf_from, '@')) != NULL)
1127  pf = ++q;
1128  break;
1129  }
1130 
1131  switch (rcptFlags) {
1132  case GREY_EMAIL_NONE:
1133  *pt = '\0';
1134  break;
1135  case GREY_EMAIL_FULL:
1136  break;
1137  case GREY_EMAIL_USER:
1138  if ((q = strchr(buf_rcpt, '@')) != NULL)
1139  *q = '\0';
1140  break;
1141  case GREY_EMAIL_HOST:
1142  if ((q = strchr(buf_rcpt, '@')) != NULL)
1143  pt = ++q;
1144  break;
1145  }
1146 
1147  for (q = pi; *q != '\0'; q++) {
1148  if (iscntrl(*q) || isspace(*q) || (*q == ';') || (*q == '#'))
1149  *q = '_';
1150  }
1151  for (q = pf; *q != '\0'; q++) {
1152  if (iscntrl(*q) || isspace(*q) || (*q == ';') || (*q == '#'))
1153  *q = '_';
1154  }
1155  for (q = pt; *q != '\0'; q++) {
1156  if (iscntrl(*q) || isspace(*q) || (*q == ';') || (*q == '#'))
1157  *q = '_';
1158  }
1159 
1160  snprintf(p, sz, "%s;%s;%s", pi, pf, pt);
1161  }
1162 
1163  return p;
1164 }
1165 
1166 /* ****************************************************************************
1167  * *
1168  * *
1169  **************************************************************************** */
1170 static char *
1171 grey_key_white(ip, from)
1172  char *ip;
1173  char *from;
1174 {
1175  char *p = NULL;
1176  size_t sz = 0;
1177 
1178  ip = STRNULL(ip, "-");
1179  from = STRNULL(from, "nullsender");
1180 
1181  if (zeStrRegex(from, "<>", NULL, NULL, TRUE))
1182  from = "<>";
1183 
1184  sz = 3 * BF_SZ + 3;
1185 
1186  if ((p = malloc(sz)) == NULL) {
1187  ZE_LogSysError("malloc(%ld)", (long) sz);
1188  return NULL;
1189  }
1190 
1191  {
1192  char buf_from[BF_SZ], *pf;
1193  char buf_ip[BF_SZ], *pi;
1194  char *q;
1195 
1196  bool nullsender = FALSE;
1197 
1198  pf = buf_from;
1199  pi = buf_ip;
1200 
1201  memset(buf_from, 0, sizeof (buf_from));
1202  memset(buf_ip, 0, sizeof (buf_ip));
1203 
1204  nullsender = ISNULLSENDER(from);
1205 
1206  if (zeStrRegex(ip, IPV6_ADDR_REGEX, NULL, NULL, TRUE)) {
1207  ipv6_T ipv6;
1208 
1209  if (ipv6_str2rec(&ipv6, ip))
1210  ipv6_prefix_str(&ipv6, buf_ip, sizeof (buf_ip), 56);
1211  } else
1212  strlcpy(buf_ip, ip, sizeof (buf_ip));
1213 
1214  (void) extract_email_address(buf_from, from, sizeof (buf_from));
1215 
1216  if (nullsender)
1217  snprintf(buf_from, sizeof (buf_from), "nullsender");
1218 
1219  if ((q = strchr(buf_from, '@')) != NULL)
1220  pf = ++q;
1221 
1222  for (q = pi; *q != '\0'; q++) {
1223  if (iscntrl(*q) || isspace(*q) || (*q == '/') || (*q == ';')
1224  || (*q == '#'))
1225  *q = '_';
1226  }
1227  for (q = pf; *q != '\0'; q++) {
1228  if (iscntrl(*q) || isspace(*q) || (*q == '/') || (*q == ';')
1229  || (*q == '#'))
1230  *q = '_';
1231  }
1232 
1233  snprintf(p, sz, "%s;%s", pi, pf);
1234  }
1235 
1236  return p;
1237 }
1238 
1239 /* ****************************************************************************
1240  * *
1241  * *
1242  **************************************************************************** */
1243 static int
1244 grey_count_pending(ip)
1245  char *ip;
1246 {
1247  int nb = 0;
1248 
1249  if (ip == NULL)
1250  return 0;
1251 
1252  if (grey_cursor_open(&gdata.gdbp, TRUE)) {
1253  char key[BF_SZ], data[BF_SZ];
1254  char ipk[BF_SZ];
1255 
1256  char *q;
1257 
1258  memset(key, 0, sizeof (key));
1259  memset(data, 0, sizeof (data));
1260 
1261  strlcpy(key, ip, sizeof (key));
1262  switch (select_ip) {
1263  case GREY_ADDR_NONE:
1264  *key = '\0';
1265  break;
1266  case GREY_ADDR_FULL:
1267  break;
1268  case GREY_ADDR_NET:
1269  if ((q = strrchr(key, '.')) != NULL)
1270  *q = '\0';
1271  break;
1272  }
1273  if (strlen(key) > 0)
1274  strlcat(key, ";", sizeof (key));
1275  strlcpy(ipk, key, sizeof (ipk));
1276 
1277  if (grey_cursor_get_first
1278  (&gdata.gdbp, key, sizeof (key), data, sizeof (data))) {
1280  do {
1281  grey_entry_T entry;
1282  bool ok = TRUE;
1283 
1284  DB_BTREE_SEQ_CHECK(key, gdata.gdbp.database);
1285 
1286 #if 0
1287  if (strncmp(key, ipk, strlen(ipk)) != 0)
1288  break;
1289 #else
1290  memset(&entry, 0, sizeof (entry));
1291  (void) grey_value_str2entry(&entry, data);
1292  ok = STREQUAL(ip, entry.ip);
1293  grey_entry_free(&entry);
1294  if (!ok)
1295  break;
1296 #endif
1297  nb++;
1298  } while (grey_cursor_get_next(&gdata.gdbp, key, sizeof (key), data,
1299  sizeof (data)));
1300  DB_BTREE_SEQ_END();
1301  }
1302  (void) grey_cursor_close(&gdata.gdbp);
1303  }
1304 
1305  return nb;
1306 }
1307 
1308 /* ****************************************************************************
1309  * *
1310  * *
1311  **************************************************************************** */
1312 
1313 /*
1314 ** HI LEVEL DATABASE FUNCTIONS
1315 */
1316 
1317 /*
1318  ### #### # #####
1319  # # # # #
1320  # #### # #
1321  ### # # # #
1322 */
1323 static char *greydir = NULL;
1324 
1325 bool
1326 grey_init(workdir, rd, mode)
1327  char *workdir;
1328  bool rd;
1329  int mode;
1330 {
1331  static bool ok = FALSE;
1332  bool res;
1333 
1334  if (!ok) {
1335  atexit(grey_close);
1336  ok = TRUE;
1337  }
1338 
1339  /*
1340  * XXX JOE
1341  * ** set values from configured options
1342  */
1343 
1344  /*
1345  * First of all, from configuration file
1346  */
1347  {
1348  }
1349 
1350  /*
1351  * Now, from environnement variables
1352  */
1353  {
1354  }
1355 
1356  grey_mode = mode;
1357 
1359 
1360  greydir = workdir;
1361 
1362  GREY_CRIT_LOCK();
1363  res = db_grey_open(greydir, rd);
1364  GREY_CRIT_UNLOCK();
1365 
1366  return res;
1367 }
1368 
1369 /* ****************************************************************************
1370  * *
1371  * *
1372  **************************************************************************** */
1373 
1374 /*
1375  ### #### # #####
1376  # # # # #
1377  # #### # #
1378  ### # # # #
1379 */
1380 void
1382 {
1383  GREY_CRIT_LOCK();
1384  (void) db_grey_close();
1385  GREY_CRIT_UNLOCK();
1386 }
1387 
1388 /* ****************************************************************************
1389  * *
1390  * *
1391  **************************************************************************** */
1392 bool
1394 {
1395  bool result = TRUE;
1396 
1397  GREY_CRIT_LOCK();
1398  result = db_grey_reopen();
1399  GREY_CRIT_UNLOCK();
1400 
1401  return result;
1402 }
1403 
1404 /* ****************************************************************************
1405  * *
1406  * *
1407  **************************************************************************** */
1408 static bool
1409 grey_add_rec(h, key, value, size)
1410  ZEDB_T *h;
1411  char *key;
1412  void *value;
1413  size_t size;
1414 {
1415  bool res;
1416 
1417  zeDb_Lock(h);
1418  res = zeDb_AddRec(h, key, value, size);
1419  zeDb_Unlock(h);
1420 
1421  return res;
1422 }
1423 
1424 /* ****************************************************************************
1425  * *
1426  * *
1427  **************************************************************************** */
1428 static bool
1429 grey_get_rec(h, key, value, size)
1430  ZEDB_T *h;
1431  char *key;
1432  void *value;
1433  size_t size;
1434 {
1435  bool res;
1436 
1437  zeDb_Lock(h);
1438  res = zeDb_GetRec(h, key, value, size);
1439  zeDb_Unlock(h);
1440 
1441  return res;
1442 }
1443 
1444 /* ****************************************************************************
1445  * *
1446  * *
1447  **************************************************************************** */
1448 static bool
1449 grey_del_rec(h, key)
1450  ZEDB_T *h;
1451  char *key;
1452 {
1453  bool res;
1454 
1455  zeDb_Lock(h);
1456  res = zeDb_DelRec(h, key);
1457  zeDb_Unlock(h);
1458 
1459  return res;
1460 }
1461 
1462 /* ****************************************************************************
1463  * *
1464  * *
1465  **************************************************************************** */
1466 
1467 /*
1468  ### #### # #####
1469  # # # # #
1470  # #### # #
1471  ### # # # #
1472 */
1473 static bool
1474 grey_flush()
1475 {
1476  bool res = TRUE;
1477 
1478  GREY_CRIT_LOCK();
1479 
1480  res = db_grey_flush();
1481 
1482  GREY_CRIT_UNLOCK();
1483 
1484  return res;
1485 }
1486 
1487 /* ****************************************************************************
1488  * *
1489  * *
1490  **************************************************************************** */
1491 static bool
1492 grey_cursor_open(h, rdonly)
1493  ZEDB_T *h;
1494  bool rdonly;
1495 {
1496  bool res = FALSE;
1497 
1498  res = zeDb_CursorOpen(h, rdonly);
1499 
1500  return res;
1501 }
1502 
1503 /* ****************************************************************************
1504  * *
1505  * *
1506  **************************************************************************** */
1507 static bool
1508 grey_cursor_close(h)
1509  ZEDB_T *h;
1510 {
1511  bool res;
1512 
1513  res = zeDb_CursorClose(h);
1514 
1515  return res;
1516 }
1517 
1518 /* ****************************************************************************
1519  * *
1520  * *
1521  **************************************************************************** */
1522 static bool
1523 grey_cursor_get_first(h, k, ksz, v, vsz)
1524  ZEDB_T *h;
1525  char *k;
1526  size_t ksz;
1527  void *v;
1528  size_t vsz;
1529 {
1530  bool res;
1531 
1532  res = zeDb_CursorGetFirst(h, k, ksz, v, vsz);
1533 
1534  return res;
1535 }
1536 
1537 /* ****************************************************************************
1538  * *
1539  * *
1540  **************************************************************************** */
1541 static bool
1542 grey_cursor_get_next(h, k, ksz, v, vsz)
1543  ZEDB_T *h;
1544  char *k;
1545  size_t ksz;
1546  void *v;
1547  size_t vsz;
1548 {
1549  bool res;
1550 
1551  res = zeDb_CursorGetNext(h, k, ksz, v, vsz);
1552 
1553  return res;
1554 }
1555 
1556 /* ****************************************************************************
1557  * *
1558  * *
1559  **************************************************************************** */
1560 static bool
1561 grey_cursor_del(h)
1562  ZEDB_T *h;
1563 {
1564  bool res;
1565 
1566  res = zeDb_CursorDel(h);
1567 
1568  return res;
1569 }
1570 
1571 
1572 /* ****************************************************************************
1573  * *
1574  * *
1575  **************************************************************************** */
1576 
1577 /*
1578 ** MEDIUM LEVEL DATABASE FUNCTIONS
1579 **
1580 */
1581 static bool
1582 db_grey_open(workdir, rd)
1583  char *workdir;
1584  bool rd;
1585 {
1586  bool res = TRUE;
1587  char path[1024];
1588  int mode;
1589 
1590  if (workdir == NULL || strlen(workdir) == 0)
1591  workdir = "/tmp";
1592 
1593  if (zeDb_OK(&gdata.gdbp) && zeDb_OK(&gdata.gdbv) &&
1594  zeDb_OK(&gdata.gdbw) && zeDb_OK(&gdata.gdbb))
1595  return TRUE;
1596 
1597  rdonly = rd;
1598 
1599  mode = (rdonly ? 0444 : 0644);
1600 
1601  zeDb_Lock(&gdata.gdbp);
1602  if (!zeDb_OK(&gdata.gdbp)) {
1603  snprintf(path, sizeof (path), "%s/%s", workdir, "ze-greypend.db");
1604 
1605  res = zeDb_Open(&gdata.gdbp, work_db_env, path, mode, rdonly, TRUE, 0);
1606  ZE_MessageInfo(DBG_LEVEL, "PATH = %-32s, %s", path,
1607  STRBOOL(res, "OK", "KO"));
1608  }
1609  zeDb_Unlock(&gdata.gdbp);
1610 
1611  zeDb_Lock(&gdata.gdbv);
1612  if (!zeDb_OK(&gdata.gdbv)) {
1613  snprintf(path, sizeof (path), "%s/%s", workdir, "ze-greyvalid.db");
1614 
1615  res = zeDb_Open(&gdata.gdbv, work_db_env, path, mode, rdonly, TRUE, 0);
1616  ZE_MessageInfo(DBG_LEVEL, "PATH = %-32s, %s", path,
1617  STRBOOL(res, "OK", "KO"));
1618  }
1619  zeDb_Unlock(&gdata.gdbv);
1620 
1621  zeDb_Lock(&gdata.gdbw);
1622  if (!zeDb_OK(&gdata.gdbw)) {
1623  snprintf(path, sizeof (path), "%s/%s", workdir, "ze-greywhitelist.db");
1624 
1625  res = zeDb_Open(&gdata.gdbw, work_db_env, path, mode, rdonly, TRUE, 0);
1626  ZE_MessageInfo(DBG_LEVEL, "PATH = %-32s, %s", path,
1627  STRBOOL(res, "OK", "KO"));
1628  }
1629  zeDb_Unlock(&gdata.gdbw);
1630 
1631  zeDb_Lock(&gdata.gdbb);
1632  if (!zeDb_OK(&gdata.gdbb)) {
1633  snprintf(path, sizeof (path), "%s/%s", workdir, "ze-greyblacklist.db");
1634 
1635  res = zeDb_Open(&gdata.gdbb, work_db_env, path, mode, rdonly, TRUE, 0);
1636  ZE_MessageInfo(DBG_LEVEL, "PATH = %-32s, %s", path,
1637  STRBOOL(res, "OK", "KO"));
1638  }
1639  zeDb_Unlock(&gdata.gdbb);
1640 
1641  return res;
1642 }
1643 
1644 /* ****************************************************************************
1645  * *
1646  * *
1647  **************************************************************************** */
1648 static bool
1649 db_grey_close()
1650 {
1651  bool res = TRUE;
1652 
1653  zeDb_Lock(&gdata.gdbp);
1654  if (zeDb_OK(&gdata.gdbp))
1655  res = zeDb_Close(&gdata.gdbp);
1656  zeDb_Unlock(&gdata.gdbp);
1657 
1658  zeDb_Lock(&gdata.gdbv);
1659  if (zeDb_OK(&gdata.gdbv))
1660  res = zeDb_Close(&gdata.gdbv);
1661  zeDb_Unlock(&gdata.gdbv);
1662 
1663  zeDb_Lock(&gdata.gdbw);
1664  if (zeDb_OK(&gdata.gdbw))
1665  res = zeDb_Close(&gdata.gdbw);
1666  zeDb_Unlock(&gdata.gdbw);
1667 
1668  zeDb_Lock(&gdata.gdbb);
1669  if (zeDb_OK(&gdata.gdbb))
1670  res = zeDb_Close(&gdata.gdbb);
1671  zeDb_Unlock(&gdata.gdbb);
1672 
1673  return res;
1674 }
1675 
1676 /* ****************************************************************************
1677  * *
1678  * *
1679  **************************************************************************** */
1680 static bool
1681 db_grey_reopen()
1682 {
1683  bool res = TRUE;
1684 
1685  db_grey_close();
1686  res = db_grey_open(greydir, rdonly);
1687  return res;
1688 }
1689 
1690 /* ****************************************************************************
1691  * *
1692  * *
1693  **************************************************************************** */
1694 static bool
1695 db_grey_flush()
1696 {
1697  bool res = TRUE;
1698 
1699  zeDb_Lock(&gdata.gdbp);
1700  res = res && zeDb_Flush(&gdata.gdbp);
1701  zeDb_Unlock(&gdata.gdbp);
1702 
1703  zeDb_Lock(&gdata.gdbv);
1704  res = res && zeDb_Flush(&gdata.gdbv);
1705  zeDb_Unlock(&gdata.gdbv);
1706 
1707  zeDb_Lock(&gdata.gdbw);
1708  res = res && zeDb_Flush(&gdata.gdbw);
1709  zeDb_Unlock(&gdata.gdbw);
1710 
1711  zeDb_Lock(&gdata.gdbb);
1712  res = res && zeDb_Flush(&gdata.gdbb);
1713  zeDb_Unlock(&gdata.gdbb);
1714 
1715  if (zeDb_errno(&gdata.gdbp) == DB_RUNRECOVERY ||
1716  zeDb_errno(&gdata.gdbv) == DB_RUNRECOVERY ||
1717  zeDb_errno(&gdata.gdbw) == DB_RUNRECOVERY ||
1718  zeDb_errno(&gdata.gdbb) == DB_RUNRECOVERY) {
1720  "Reloading Greylisting databases after error (pending)");
1721  if (!(res = grey_reload())) {
1722  ZE_MessageWarning(8, "Reloading Greylisting error - restarting");
1723  kill(0, SIGTERM);
1724  sleep(1);
1725  exit(0);
1726  }
1727  }
1728 
1729  return res;
1730 }
1731 
1732 /* ****************************************************************************
1733  * *
1734  * *
1735  **************************************************************************** */
1736 
1737 /*
1738 ** GREY DATABASE CLEANUP
1739 */
1740 #define SIGTID ((pthread_t ) 23021957)
1741 
1742 static void *grey_task(void *);
1743 static pthread_t tid = SIGTID;
1744 static time_t tlast = (time_t) 0;
1745 
1746 void
1748 {
1749  int r;
1750 
1751  if (tid != SIGTID && (time(NULL) - tlast > 2 * dt_grey_cleanup)) {
1752  ZE_LogSysWarning("grey_task thread not running ???");
1753  tid = SIGTID;
1754  }
1755 
1756  if (tid == SIGTID) {
1757  ZE_MessageInfo(9, "*** Starting grey_task thread ...");
1758 
1759  if ((r = pthread_create(&tid, NULL, grey_task, (void *) NULL)) != 0)
1760  ZE_LogSysError("Couldn't launch periodic_tasks_loop");
1761  }
1762 }
1763 
1764 
1765 /* ****************************************************************************
1766  * *
1767  * *
1768  **************************************************************************** */
1769 static uint32_t grey_dw_flags = GREY_DW_NONE;
1770 
1771 void
1773  char *s;
1774  bool reset;
1775 {
1776  char *argv[32];
1777  int argc = 0;
1778  int i;
1779  char *ts = NULL;
1780 
1781  if (s == NULL)
1782  return;
1783 
1784  if (reset)
1785  grey_dw_flags = GREY_DW_NONE;
1786 
1787  if (strlen(s) == 0)
1788  return;
1789 
1790  if ((ts = strdup(s)) == NULL) {
1791  ZE_LogSysError("strdup(%s) error", s);
1792  return;
1793  }
1794 
1795  memset(argv, 0, sizeof (argv));
1796  argc = zeStr2Tokens(s, 32, argv, " ,|");
1797 
1798  for (i = 0; i < argc; i++) {
1799  if (strcasecmp(argv[i], "ALL") == 0) {
1800  grey_dw_flags = GREY_DW_ALL;
1801  break;
1802  }
1803 
1804  if (strcasecmp(argv[i], "NONE") == 0) {
1805  grey_dw_flags = GREY_DW_NONE;
1806  break;
1807  }
1808 
1809  if (strcasecmp(argv[i], "NullSender") == 0) {
1810  grey_dw_flags |= GREY_DW_NULLSENDER;
1811  continue;
1812  }
1813  if (strcasecmp(argv[i], "BadResolve") == 0) {
1814  grey_dw_flags |= GREY_DW_BAD_RESOLVE;
1815  continue;
1816  }
1817  if (strcasecmp(argv[i], "DomainMatch") == 0) {
1818  grey_dw_flags |= GREY_DW_DOMAIN_MISMATCH;
1819  continue;
1820  }
1821  if (strcasecmp(argv[i], "BadRCPT") == 0) {
1822  grey_dw_flags |= GREY_DW_BAD_RCPT;
1823  continue;
1824  }
1825  if (strcasecmp(argv[i], "SpamTrap") == 0) {
1826  grey_dw_flags |= GREY_DW_SPAMTRAP;
1827  continue;
1828  }
1829  if (strcasecmp(argv[i], "BadMX") == 0) {
1830  grey_dw_flags |= GREY_DW_BAD_MX;
1831  continue;
1832  }
1833  if (strcasecmp(argv[i], "BadClient") == 0) {
1834  grey_dw_flags |= GREY_DW_BAD_CLIENT;
1835  continue;
1836  }
1837  if (strcasecmp(argv[i], "Spammer") == 0) {
1838  grey_dw_flags |= GREY_DW_BAD_CLIENT;
1839  continue;
1840  }
1841  }
1842 
1843  FREE(ts);
1844 }
1845 
1846 
1847 
1848 /* ****************************************************************************
1849  * *
1850  * *
1851  **************************************************************************** */
1852 
1853 #define TIMER_INIT(t) \
1854  do { \
1855  t = zeTime_ms(); \
1856  } while (0)
1857 
1858 #define TIMER_NOW(t) (zeTime_ms() - t)
1859 
1860 #define TIMER_LOG(s, t) \
1861  do { \
1862  timems_T dt = TIMER_NOW(t); \
1863  ZE_MessageInfo(0, "%-12s : Elapsed time %ld ms",s, (long ) (dt)); \
1864  } while (0)
1865 
1866 
1867 struct expire_st_T {
1868  char key[3 * BF_SZ];
1869  long nkt;
1870  long nke;
1871 };
1872 
1873 /*
1874  ### #### # #####
1875  # # # # #
1876  # #### # #
1877  ### # # # #
1878 */
1879 static bool
1880 grey_database_expire(h, st, tmax_norm, tmax_null, gdb)
1881  ZEDB_T *h;
1882  expire_st_T *st;
1883  time_t tmax_norm;
1884  time_t tmax_null;
1885  int gdb;
1886 {
1887  bool ok = FALSE;
1888  time_t now = time(NULL);
1889 
1890  char tkey[3 * BF_SZ];
1891  char *key = tkey;
1892  size_t ksz = sizeof (tkey);
1893  char *label = "";
1894 
1895  timems_T tims;
1896  timems_T dt_lock_max = 1000;
1897  char kbuf[1024];
1898 
1899  switch (gdb) {
1900  case GDB_PENDING:
1901  label = "Pending";
1902  break;
1903  case GDB_VALID:
1904  label = "Valid";
1905  break;
1906  case GDB_WHITELIST:
1907  label = "Whitelist";
1908  break;
1909  case GDB_BLACKLIST:
1910  label = "Blacklist";
1911  break;
1912  default:
1913  return FALSE;
1914  break;
1915  }
1916 
1917  ZE_MessageInfo(10, "Entering %s (%s)", ZE_FUNCTION, label);
1918 
1919  {
1920  char *env = NULL;
1921  time_t dt = dt_lock_max;
1922 
1923  if ((env = getenv("GREY_CLEANUP_DT_LOCK_MAX")) != NULL) {
1924  dt = zeStr2ulong(env, NULL, dt);
1925  if (dt >= 500)
1926  dt_lock_max = dt;
1927  }
1928  }
1929 
1930  if (st != NULL) {
1931  key = st->key;
1932  ksz = sizeof (st->key);
1933  if (strlen(key) == 0)
1934  st->nkt = st->nke = 0;
1935  }
1936 
1937  GREY_CRIT_LOCK();
1938 
1939  TIMER_INIT(tims);
1940 
1941  memset(kbuf, 0, sizeof (kbuf));
1942  if (grey_cursor_open(h, FALSE)) {
1943  char data[BF_SZ];
1944  char ip[BF_SZ];
1945  bool ip_bad = FALSE;
1946 
1947  bool check_bad_clients;
1948  bool check_domain_match;
1949  int ntp = 0;
1950 
1951  check_bad_clients = (grey_dw_flags != GREY_DW_NONE);
1952  check_domain_match =
1953  ((grey_dw_flags & GREY_DW_DOMAIN_MISMATCH) != GREY_DW_NONE);
1954 
1955  {
1956  char *env = NULL;
1957 
1958  env = getenv("GREY_CHECK_BAD_CLIENTS");
1959  if (env != NULL && strcasecmp(env, "YES") == 0)
1960  check_bad_clients = TRUE;
1961 
1962  env = getenv("GREY_CHECK_DOMAIN_MATCH");
1963  if (env != NULL && strcasecmp(env, "YES") == 0)
1964  check_domain_match = TRUE;
1965  }
1966 
1967  memset(data, 0, sizeof (data));
1968  memset(ip, 0, sizeof (ip));
1969 
1971  for (ok = grey_cursor_get_first(h, key, ksz, data, sizeof (data));
1972  ok; ok = grey_cursor_get_next(h, key, ksz, data, sizeof (data))) {
1973  time_t last;
1974  char *argvk[GREY_ARGS];
1975  int argck;
1976  char *argvv[GREY_ARGS];
1977  int argcv;
1978  char *from = NULL;
1979  bool nullsender = FALSE;
1980  time_t t_max = tmax_norm;
1981  char *why = "";
1982  char *hostname = NULL;
1983  int coef = 1;
1984  char *separator = ";";
1985 
1986  DB_BTREE_SEQ_CHECK(key, h->database);
1987 
1988 #if 0
1989  ZE_MessageInfo(10, "-> key %s / value %s", key, data);
1990 #endif
1991 
1992  ntp++;
1993  if (st != NULL)
1994  st->nkt++;
1995 
1996  why = "";
1997  hostname = NULL;
1998  coef = 1;
1999 
2000  strlcpy(kbuf, key, sizeof (kbuf));
2001  argck = zeStr2Tokens(kbuf, GREY_ARGS, argvk, ";");
2002  if (argck == 0 || argvk[0] == NULL || argvk[1] == NULL
2003  || argvk[2] == NULL) {
2004  /*
2005  * XXX ???
2006  */
2007  }
2008 
2009  separator = grey_separator(data);
2010  argcv = zeStr2Tokens(data, GREY_ARGS, argvv, separator);
2011 
2012  if (argcv == 0) {
2013  ZE_MessageInfo(10, "key %s has empty value", key);
2014  (void) grey_cursor_del(h);
2015  if (st != NULL)
2016  st->nke++;
2017  continue;
2018  }
2019 
2020  if (argvv[ARG_DATE_UPDT] == NULL)
2021  continue;
2022 
2023  /*
2024  * utiliser entries data rec
2025  */
2026  errno = 0;
2027  last = (time_t) zeStr2ulong(argvv[ARG_DATE_UPDT], NULL, 0);
2028 
2029  if (gdb == GDB_WHITELIST) {
2030  /*
2031  * XXX check if entry is too old and delete it if so
2032  */
2033 
2034  /*
2035  * continue;
2036  */
2037 
2038  goto endlabel;
2039  }
2040 
2041  if (gdb == GDB_BLACKLIST) {
2042  /*
2043  * XXX check if entry is too old and delete it if so
2044  */
2045 
2046  /*
2047  * continue;
2048  */
2049 
2050  goto endlabel;
2051  }
2052 
2053  argvv[ARG_IP] = STRNULL(argvv[ARG_IP], "XXX");
2054  if (strcasecmp(argvv[ARG_IP], ip) != 0) {
2055  ip_bad = FALSE;
2056 
2057  strlcpy(ip, argvv[ARG_IP], sizeof (ip));
2058 
2059  if (check_bad_clients)
2060  ip_bad = grey_check_bad_smtp_client(ip, grey_dw_flags);
2061  }
2062 
2063  if (ip_bad) {
2064  coef *= 4;
2065  why = "bad ip";
2066  ZE_MessageInfo(11, "* Removing %s (%s)", key, why);
2067  (void) grey_cursor_del(h);
2068  if (st != NULL)
2069  st->nke++;
2070  continue;
2071  }
2072 
2073  from = argvv[ARG_FROM];
2074  nullsender = ISNULLSENDER(from);
2075  if (nullsender) {
2076  t_max = tmax_null;
2077 
2078  why = "nullsender";
2079  }
2080 
2081  if (check_domain_match && !nullsender) {
2082  char *pfrom, *pname;
2083 
2084  pfrom = strchr(from, '@');
2085  if (pfrom != NULL)
2086  pfrom++;
2087  else
2088  pfrom = from;
2089 
2090  pname = argvv[ARG_HOSTNAME];
2091  if ((pname != NULL && strlen(pname) > 0) &&
2092  !compatible_domainnames(pfrom, pname)) {
2093  coef *= 2;
2094  why = "domain";
2095  }
2096  }
2097 
2098  endlabel:
2099 
2100  if (coef > 1) {
2101  t_max /= coef;
2102  t_max = MAX(t_max, T_EXPIRE_BAD_MIN);
2103  switch (gdb) {
2104  case GDB_PENDING:
2105  t_max = MIN(t_max, T_EXPIRE_PENDING_BAD_MAX);
2106  break;
2107  case GDB_VALID:
2108  t_max = MIN(t_max, T_EXPIRE_VALID_BAD_MAX);
2109  break;
2110  default:
2111  break;
2112  }
2113  }
2114 
2115  if (last + t_max < now) {
2116  why = STRNULL(why, "");
2117  if (strcmp(why, "") == 0)
2118  why = "too old";
2119 
2121  char logstr[1024];
2122  void log_grey_expire(char *);
2123 
2124  ZE_MessageInfo(11, "* Removing %s %s (%s %s %s)",
2125  STRNULL(label, "-"), key, why, from, STRNULL(hostname,
2126  "-"));
2127 
2128  memset(logstr, 0, sizeof (logstr));
2129 
2130  /*
2131  * timestamp DB=(...) CREATED=(...) UPDATED=(...) IP=(...) FROM=(...) TO=(...) WHY=(...)
2132  */
2133  snprintf(logstr, sizeof (logstr),
2134  "DB=(%s) WHY=(%s) CREATED=(%s) UPDATED=(%s) IP=(%s) "
2135  "HOSTNAME=(%s) FROM=(%s) TO=(%s) KEY=(%s/%s/%s)",
2136  label, why, argvv[ARG_DATE_INIT], argvv[ARG_DATE_UPDT],
2137  argvv[ARG_IP], argvv[ARG_HOSTNAME], argvv[ARG_FROM],
2138  STRNULL(argvk[2], "-"),
2139  STRNULL(argvk[0], "-"),
2140  STRNULL(argvk[1], "-"), STRNULL(argvk[2], "-"));
2141 
2142  log_grey_expire(logstr);
2143  }
2144 
2145  (void) grey_cursor_del(h);
2146  if (st != NULL)
2147  st->nke++;
2148  }
2149 
2150  if (last + t_max > now) {
2151 
2152  }
2153  if ((ntp % 1000) == 0) {
2154  /*
2155  * int n = smtprate_check(RATE_CONN, "", 600);
2156  */
2157  /*
2158  * check load - maybe...
2159  */
2160  if (TIMER_NOW(tims) > dt_lock_max) {
2161  ZE_MessageInfo(10,
2162  "Handling %s database : max delay expired : %d entries handled",
2163  label, ntp);
2164 
2165  ok = TRUE;
2166  break;
2167  }
2168  }
2169  }
2170  (void) grey_cursor_close(h);
2171  DB_BTREE_SEQ_END();
2172  }
2173 
2174  TIMER_LOG(label, tims);
2175 
2176  GREY_CRIT_UNLOCK();
2177 
2178  return !ok;
2179 }
2180 
2181 /* ****************************************************************************
2182  * *
2183  * *
2184  **************************************************************************** */
2185 #if 0
2186 static int
2187 count_members(s, sep)
2188  char *s;
2189  int sep;
2190 {
2191  int nb = 1;
2192 
2193  if (s == NULL || strlen(s) == 0)
2194  return 0;
2195 
2196  while ((s = strchr(s, sep)) != NULL) {
2197  nb++;
2198  s++;
2199  }
2200 
2201  return nb;
2202 }
2203 #endif
2204 
2205 static bool
2206 grey_list2white(dbw, list)
2207  ZEDB_T *dbw;
2208  LISTR_T *list;
2209 {
2210  LISTR_T *lst;
2211  time_t now = time(NULL);
2212 
2213  for (lst = list; lst != NULL; lst = lst->next) {
2214  char wkey[256], wval[256];
2215  grey_entry_T entry, *ep;
2216  LISTR_T *p;
2217  int nbdomains, nbentries, nbhits;
2218  int n;
2219 
2220  if (lst->count < MIN_CNT_PER_DOMAIN)
2221  continue;
2222 
2223  memset(&entry, 0, sizeof (entry));
2224  /*
2225  ** Shall check if the number of domains for this IP
2226  ** isn't too high
2227  */
2228  nbdomains = nbentries = nbhits = 0;
2229 
2230  /*
2231  * IPV6 - / or ; ?
2232  */
2233  n = strcspn(lst->key, ";");
2234  if (n == strlen(lst->key)) {
2235  /*
2236  * Only IP ???
2237  */
2238  continue;
2239  }
2240  n++;
2241 
2242  for (p = list; p != NULL; p = p->next) {
2243  nbentries++;
2244  if (strncasecmp(lst->key, p->key, n) == 0) {
2245  nbdomains++;
2246  nbhits += p->count;
2247  }
2248  }
2249  /*
2250  * evaluate function(nbdomains, nbhits, lst->n, entry age
2251  */
2252  /*
2253  * XXX define function
2254  */
2255  if (nbentries == 0)
2256  continue;
2257  if (0)
2258  continue;
2259 
2260  /*
2261  **
2262  ** If not, then add this IP/domain to the whitelist
2263  */
2264 
2265  /*
2266  * XXX JOE : wkey = grey_key(GDB_WHITE, ...);
2267  */
2268  strlcpy(wkey, lst->key, sizeof (wkey));
2269 
2270  ZE_MessageInfo(10, "Adding to whitelist : %3d %s", lst->count, wkey);
2271 
2272  snprintf(wval, sizeof (wval), "%lu:%lu:%d", now, now, lst->count);
2273 
2274  ep = (grey_entry_T *) lst->data;
2275  if (ep != NULL) {
2276  char *p;
2277 
2278  strlcpy(entry.vip, STREMPTY(ep->vip, "0.0.0.0"), sizeof (entry.vip));
2279  p = strchr(ep->vfrom, '@');
2280  if (p != NULL)
2281  p++;
2282  strlcpy(entry.vfrom, STRNULL(p, "nullsender"), sizeof (entry.vfrom));
2283  strlcpy(entry.vrcpt, STREMPTY(ep->vrcpt, "nullrcpt"),
2284  sizeof (entry.vrcpt));
2285  strlcpy(entry.vhostname, STREMPTY(ep->vhostname, "UNKNOWN"),
2286  sizeof (entry.vhostname));
2287  entry.count = lst->count;
2288 
2289  strlcpy(entry.ip, STREMPTY(ep->ip, "0.0.0.0"), sizeof (entry.ip));
2290  p = strchr(ep->vfrom, '@');
2291  if (p != NULL)
2292  p++;
2293 
2294  strlcpy(entry.from, STRNULL(p, "nullsender"), sizeof (entry.from));
2295  strlcpy(entry.rcpt, STREMPTY(ep->rcpt, "nullrcpt"), sizeof (entry.rcpt));
2296  strlcpy(entry.hostname, STREMPTY(ep->vhostname, "UNKNOWN"),
2297  sizeof (entry.hostname));
2298 
2299  grey_value_entry2str(wval, &entry, sizeof (wval));
2300  }
2301 
2302  (void) grey_add_rec(dbw, wkey, wval, strlen(wval));
2303 
2304  grey_entry_free(&entry);
2305  }
2306 
2307  return TRUE;
2308 }
2309 
2310 /* ****************************************************************************
2311  * *
2312  * *
2313  **************************************************************************** */
2314 static bool
2315 grey_database_whitelist(dba, dbb, st)
2316  ZEDB_T *dba;
2317  ZEDB_T *dbb;
2318  expire_st_T *st;
2319 {
2320  bool ok = FALSE;
2321 
2322  ZE_MessageInfo(10, "Entering %s", ZE_FUNCTION);
2323 
2324  GREY_CRIT_LOCK();
2325 
2326  /*
2327  * TIMER_INIT();
2328  */
2329 
2330  if (grey_cursor_open(dba, FALSE)) {
2331  char data[BF_SZ];
2332  char key[BF_SZ];
2333  size_t ksz = sizeof (key);
2334 
2335  char cur_prefix[BF_SZ];
2336  char new_prefix[BF_SZ];
2337  int cnt_prefix;
2338  int nbw = 0;
2339  LISTR_T *list = NULL;
2340  time_t now = time(NULL);
2341 
2342  memset(key, 0, sizeof (key));
2343  memset(data, 0, sizeof (data));
2344  memset(cur_prefix, 0, sizeof (cur_prefix));
2345  memset(new_prefix, 0, sizeof (new_prefix));
2346  cnt_prefix = 0;
2347 
2349  for (ok = grey_cursor_get_first(dba, key, ksz, data, sizeof (data));
2350  ok; ok = grey_cursor_get_next(dba, key, ksz, data, sizeof (data))) {
2351  char *argv[GREY_ARGS];
2352  int argc;
2353 
2354  DB_BTREE_SEQ_CHECK(key, dba->database);
2355 
2356  argc = zeStr2Tokens(key, GREY_ARGS, argv, ";");
2357  if (argc < 3)
2358  continue;
2359 
2360  /*
2361  * Evaluate new prefix
2362  * **
2363  */
2364  {
2365  char *p;
2366 
2367  p = strchr(argv[1], '@');
2368  if (p == NULL)
2369  p = argv[1];
2370  else
2371  p++;
2372 
2373  snprintf(new_prefix, sizeof (new_prefix), "%s;%s", argv[0], p);
2374  }
2375 
2376  if (strcasecmp(cur_prefix, new_prefix) != 0) {
2377  if (cnt_prefix > 6) {
2378 
2379  nbw++;
2380  }
2381 
2382  strlcpy(cur_prefix, new_prefix, sizeof (cur_prefix));
2383  cnt_prefix = 1;
2384 
2385  grey_list2white(dbb, list);
2386 
2387  (void) zeLinkedList_Clear(list, NULL);
2388  list = NULL;
2389  } else
2390  cnt_prefix++;
2391 
2392  /*
2393  * update linked list
2394  */
2395  {
2396  grey_entry_T entry;
2397  char lkey[256], lval[256];
2398  int nb = 1;
2399 
2400  memset(&entry, 0, sizeof (entry));
2401 
2402  snprintf(lkey, sizeof (lkey), "%s %s", argv[0], argv[1]);
2403 
2404  ZE_MessageInfo(15, "DATA : %s", data);
2405 
2406  if (grey_value_str2entry(&entry, data)) {
2407  char *p = entry.from;
2408 
2409  ZE_MessageInfo(15, "get_value_str2entry OK ");
2410  p = strchr(entry.from, '@');
2411  if (p != NULL)
2412  p++;
2413  else
2414  p = entry.from;
2415 
2416  ZE_MessageInfo(15, "ENTRY : from=%s p=%s vip=%s", entry.from, p,
2417  entry.ip);
2418  snprintf(lkey, sizeof (lkey), "%s;%s", entry.ip, p);
2419 
2420  nb = entry.count;
2421  } else
2422  continue;
2423 
2424  /*
2425  * check if already whitelisted,
2426  * ** if yes, remove this entry
2427  * ** and continue
2428  */
2429  if (grey_get_rec(dbb, lkey, lval, sizeof (lval))) {
2430  if (st != NULL)
2431  st->nke++;
2432  (void) grey_cursor_del(dba);
2433  grey_entry_free(&entry);
2434  continue;
2435  }
2436 
2437  /*
2438  * Don't use entries newer than 3 days - why 3 days ???
2439  */
2440  if (entry.date_init + 3 DAYS > now)
2441  continue;
2442 
2443  /*
2444  * don't include entries if domains doesn't match
2445  */
2446  {
2447  char from[256];
2448 
2449  (void) extract_host_from_email_address(from, entry.from,
2450  sizeof (from));
2451  if (!compatible_domainnames(from, entry.hostname)) {
2452  continue;
2453  }
2454  }
2455 
2456  /*
2457  * No - let's add this record to linked list
2458  */
2459  list = zeLinkedList_Add(list, lkey, nb, &entry, sizeof (entry));
2460  }
2461  }
2462  DB_BTREE_SEQ_END();
2463 
2464  /*
2465  * XXX only for valid database...
2466  */
2467  /*
2468  * browse is done !
2469  */
2470  grey_list2white(dbb, list);
2471  (void) zeLinkedList_Clear(list, NULL);
2472  list = NULL;
2473 
2474  (void) grey_cursor_close(dba);
2475  }
2476  /*
2477  * TIMER_LOG();
2478  */
2479 
2480  GREY_CRIT_UNLOCK();
2481 
2482  return TRUE;
2483 }
2484 
2485 /* ****************************************************************************
2486  * *
2487  * *
2488  **************************************************************************** */
2489 #define ST_IDLE 0
2490 #define ST_PENDING 1
2491 #define ST_VALID 2
2492 #define ST_WHITE 3
2493 #define ST_BLACK 4
2494 #define ST_DONE 5
2495 
2496 #if 0
2497 #define CHECK_DELAY() \
2498  { \
2499  if (time(NULL) - now > 2) \
2500  continue; \
2501  }
2502 #else
2503 #define CHECK_DELAY()
2504 #endif
2505 
2506 static void *
2507 grey_task(data)
2508  void *data;
2509 {
2510  time_t now, thlast;
2511  time_t tbase;
2512  expire_st_T p_st, v_st, w_st, b_st;
2513 
2514  int upd_state = ST_IDLE;
2515 
2516  time_t dt_grey_sub;
2517 
2518  now = time(NULL);
2519  tbase = thlast = now;
2520 
2521  memset(&p_st, 0, sizeof (p_st));
2522  memset(&v_st, 0, sizeof (v_st));
2523  memset(&w_st, 0, sizeof (w_st));
2524  memset(&b_st, 0, sizeof (b_st));
2525 
2526  dt_grey_sub = 2 MINUTES;
2527  {
2528  char *env = NULL;
2529  time_t dt = dt_grey_sub;
2530 
2531  if ((env = getenv("GREY_CLEANUP_SUB_INTERVAL")) != NULL) {
2532  dt = zeStr2time(env, NULL, dt);
2533  if (dt >= 1 MINUTES)
2534  dt_grey_sub = dt;
2535  }
2536  }
2537 
2538  tbase = now;
2539 
2540  tbase = thlast = 0;
2541  for (;;) {
2542  tlast = now;
2543 
2544  ZE_MessageInfo(12, "%s running : %ld", ZE_FUNCTION, time(NULL));
2545 
2546  sleep(DT_GREY_SLEEP);
2547 
2548  now = time(NULL);
2549 
2550  if (tbase + dt_grey_cleanup <= now) {
2551  if (upd_state == ST_IDLE) {
2552  upd_state = ST_PENDING;
2553  tbase = now;
2554  }
2555  }
2556 
2557  if (upd_state == ST_IDLE)
2558  continue;
2559 
2560  if ((thlast + dt_grey_sub) <= now) {
2561  thlast = now;
2562 
2563  /*
2564  * pending entries database
2565  */
2566  if (upd_state == ST_PENDING) {
2567  bool done;
2568 
2569  ZE_MessageInfo(12, "GREY_TASK state = %d; key : %s", upd_state,
2570  p_st.key);
2571  done =
2572  grey_database_expire(&gdata.gdbp, &p_st, grey_tp_max_norm,
2573  grey_tp_max_null, GDB_PENDING);
2574  if (done) {
2575  gdata.nbp = p_st.nkt;
2576  memset(p_st.key, 0, sizeof (p_st.key));
2577  upd_state = ST_VALID;
2578  }
2579  }
2580  /*
2581  * CHECK_DELAY();
2582  */
2583 
2584  /*
2585  * valid entries database
2586  */
2587  if (upd_state == ST_VALID) {
2588  bool done;
2589 
2590  ZE_MessageInfo(12, "GREY_TASK state = %d; key : %s", upd_state,
2591  v_st.key);
2592  done =
2593  grey_database_expire(&gdata.gdbv, &v_st, grey_tv_max, 12 HOURS,
2594  GDB_VALID);
2595  if (done) {
2596 
2597  (void) grey_database_whitelist(&gdata.gdbv, &gdata.gdbw, &v_st);
2598 
2599  gdata.nbv = v_st.nkt;
2600  memset(v_st.key, 0, sizeof (v_st.key));
2601  upd_state = ST_WHITE;
2602  }
2603  }
2604  /*
2605  * CHECK_DELAY();
2606  */
2607 
2608  /*
2609  * whitelist
2610  */
2611  if (upd_state == ST_WHITE) {
2612  bool done;
2613 
2614  ZE_MessageInfo(12, "GREY_TASK state = %d; key : %s", upd_state,
2615  w_st.key);
2616  done =
2617  grey_database_expire(&gdata.gdbw, &w_st, grey_tw_max, 12 HOURS,
2618  GDB_WHITELIST);
2619  if (done) {
2620  gdata.nbw = w_st.nkt;
2621  memset(w_st.key, 0, sizeof (w_st.key));
2622  upd_state = ST_BLACK;
2623  }
2624  }
2625  /*
2626  * CHECK_DELAY();
2627  */
2628 
2629  /*
2630  * blacklist
2631  */
2632  if (upd_state == ST_BLACK) {
2633  bool done = FALSE;
2634 
2635  ZE_MessageInfo(12, "GREY_TASK state = %d; key : %s", upd_state,
2636  b_st.key);
2637  done =
2638  grey_database_expire(&gdata.gdbb, &b_st, grey_tb_max, 12 HOURS,
2639  GDB_BLACKLIST);
2640  if (done) {
2641  gdata.nbb = b_st.nkt;
2642  memset(b_st.key, 0, sizeof (b_st.key));
2643  upd_state = ST_DONE;
2644  }
2645  }
2646  /*
2647  * CHECK_DELAY();
2648  */
2649 
2650  if (upd_state == ST_DONE) {
2651  ZE_MessageInfo(10,
2652  "GREY database cleanup : pending=%d/%d valid=%d/%d white=%d/%d",
2653  p_st.nke, p_st.nkt, v_st.nke, v_st.nkt, w_st.nke,
2654  w_st.nkt);
2655  p_st.nke = p_st.nkt = v_st.nke = v_st.nkt = w_st.nke = w_st.nkt = 0;
2656 
2657  upd_state = ST_IDLE;
2658  }
2659  /*
2660  * CHECK_DELAY();
2661  */
2662  }
2663  }
2664 
2665 fin:
2666 
2667  ZE_LogMsgError(0, "Error exiting thread");
2668  exit(EX_SOFTWARE);
2669 
2670  return NULL;
2671 }
2672 
2673 /* ****************************************************************************
2674  * *
2675  * *
2676  **************************************************************************** */
2677 
2678 /*
2679  ### #### # #####
2680  # # # # #
2681  # #### # #
2682  ### # # # #
2683 */
2684 int
2685 grey_dump(fd, which, dt)
2686  int fd;
2687  char *which;
2688  time_t dt;
2689 {
2690  int nb = 0;
2691  ZEDB_T *db = NULL;
2692 
2693  if (which == NULL)
2694  return 0;
2695 
2696  if (STRCASEEQUAL(which, "PENDING"))
2697  db = &gdata.gdbp;
2698  if (STRCASEEQUAL(which, "VALID"))
2699  db = &gdata.gdbv;
2700  if (STRCASEEQUAL(which, "WHITELIST"))
2701  db = &gdata.gdbw;
2702  if (STRCASEEQUAL(which, "WHITE"))
2703  db = &gdata.gdbw;
2704 
2705  if (db == NULL)
2706  return 0;
2707 
2708  GREY_CRIT_LOCK();
2709 
2710  /*
2711  * lock ???
2712  */
2713  if (grey_cursor_open(db, TRUE)) {
2714  char key[BF_SZ], data[BF_SZ];
2715  time_t now;
2716 
2717  memset(key, 0, sizeof (key));
2718  memset(data, 0, sizeof (data));
2719 
2720  now = time(NULL);
2721  errno = 0;
2722  if (grey_cursor_get_first(db, key, sizeof (key), data, sizeof (data))) {
2723  char *argvv[GREY_ARGS];
2724  int argcv;
2725  char buf[256];
2726 
2728  do {
2729  DB_BTREE_SEQ_CHECK(key, db->database);
2730 
2731  if (dt > 0) {
2732  time_t t;
2733 
2734  strlcpy(buf, data, sizeof (buf));
2735  argcv = zeStr2Tokens(buf, GREY_ARGS, argvv, ";");
2736  if (argcv < 2)
2737  continue;
2738 
2739  t = zeStr2ulong(argvv[1], NULL, 0);
2740  if (t == 0 || t + dt <= now)
2741  continue;
2742  }
2743 
2744  if (!sd_printf(fd, "%s %s\r\n", key, data))
2745  break;
2746  nb++;
2747  } while (grey_cursor_get_next
2748  (db, key, sizeof (key), data, sizeof (data)));
2749  DB_BTREE_SEQ_END();
2750  }
2751  (void) grey_cursor_close(db);
2752  }
2753  /*
2754  * unlock ???
2755  */
2756 
2757  GREY_CRIT_UNLOCK();
2758 
2759  return nb;
2760 }
2761 
2762 /* ****************************************************************************
2763  * *
2764  * *
2765  **************************************************************************** */
2766 
2767 /*
2768  ### #### # #####
2769  # # # # #
2770  # #### # #
2771  ### # # # #
2772 */
2773 int
2774 grey_upload(fname, which)
2775  char *fname;
2776  char *which;
2777 {
2778  int nb = 0;
2779  ZEDB_T *db = NULL;
2780 
2781  if (which == NULL)
2782  return 0;
2783 
2784  if (STRCASEEQUAL(which, "PENDING"))
2785  db = &gdata.gdbp;
2786  if (STRCASEEQUAL(which, "VALID"))
2787  db = &gdata.gdbv;
2788  if (STRCASEEQUAL(which, "WHITELIST"))
2789  db = &gdata.gdbw;
2790  if (STRCASEEQUAL(which, "WHITE"))
2791  db = &gdata.gdbw;
2792 
2793  if (db == NULL)
2794  return 0;
2795 
2796  GREY_CRIT_LOCK();
2797 
2798  /*
2799  * lock ???
2800  */
2801  if (grey_cursor_open(db, TRUE)) {
2802  char key[BF_SZ], data[BF_SZ];
2803 
2804  memset(key, 0, sizeof (key));
2805  memset(data, 0, sizeof (data));
2806 
2807  errno = 0;
2808  if (grey_cursor_get_first(db, key, sizeof (key), data, sizeof (data))) {
2810  do {
2811  DB_BTREE_SEQ_CHECK(key, db->database);
2812 #if 0
2813  if (0) {
2814  time_t t;
2815  char *argvv[GREY_ARGS];
2816  int argcv;
2817  char buf[256];
2818 
2819  strlcpy(buf, data, sizeof (buf));
2820  argcv = zeStr2Tokens(buf, GREY_ARGS, argvv, ";");
2821  if (argcv < 2)
2822  continue;
2823 
2824  t = zeStr2ulong(argvv[1], NULL, 0);
2825  }
2826 #endif
2827  nb++;
2828  } while (grey_cursor_get_next
2829  (db, key, sizeof (key), data, sizeof (data)));
2830  DB_BTREE_SEQ_END();
2831  }
2832  (void) grey_cursor_close(db);
2833  }
2834  /*
2835  * unlock ???
2836  */
2837 
2838  GREY_CRIT_UNLOCK();
2839 
2840  return nb;
2841 }
2842 
2843 /* ****************************************************************************
2844  * *
2845  * *
2846  **************************************************************************** */
2847 static char *
2848 grey_separator(s)
2849  char *s;
2850 {
2851  static char *sep = ";";
2852 
2853  if (s != NULL && strlen(s) > 0) {
2854  int l;
2855 
2856  l = strspn(s, "0123456789");
2857  switch (s[l]) {
2858  case ':':
2859  sep = ":";
2860  break;
2861  case ';':
2862  sep = ";";
2863  break;
2864  }
2865  }
2866  return sep;
2867 }
2868 
2869 static void
2870 grey_entry_free(entry)
2871  grey_entry_T *entry;
2872 {
2873  if (entry == NULL)
2874  return;
2875 
2876  memset(entry, 0, sizeof (*entry));
2877 }
2878 
2879 static bool
2880 grey_value_str2entry(entry, s)
2881  grey_entry_T *entry;
2882  char *s;
2883 {
2884  char *argv[GREY_ARGS];
2885  int argc;
2886  char *tstr = NULL;
2887 
2888  char *separator = ";";
2889 
2890  /*
2891  * memset(entry, 0, sizeof (*entry));
2892  */
2893 
2894  if ((tstr = strdup(s)) == NULL) {
2895  ZE_LogSysError("strdup(%s) error", s);
2896  return FALSE;
2897  }
2898 
2899  separator = grey_separator(s);
2900  argc = zeStr2Tokens(tstr, GREY_ARGS, argv, separator);
2901  if (argc > ARG_DATE_INIT) {
2902  time_t t;
2903 
2904  errno = 0;
2905  t = (time_t) zeStr2ulong(argv[ARG_DATE_INIT], NULL, 0);
2906  if (errno != EINVAL && errno != ERANGE)
2907  entry->date_init = t;
2908  else
2909  ZE_LogSysWarning("Conversion %s to DATE_INIT error", argv[ARG_DATE_INIT]);
2910  }
2911 
2912  if (argc > ARG_DATE_UPDT) {
2913  time_t t;
2914 
2915  errno = 0;
2916  t = (time_t) zeStr2ulong(argv[ARG_DATE_UPDT], NULL, 0);
2917  if (errno != EINVAL && errno != ERANGE)
2918  entry->date_updt = t;
2919  else
2920  ZE_LogSysWarning("Conversion %s to DATE_UPDT error", argv[ARG_DATE_UPDT]);
2921  }
2922 
2923  if (argc > ARG_IP) {
2924  strlcpy(entry->ip, STRNULL(argv[ARG_IP], "0.0.0.0"), sizeof (entry->ip));
2925  strlcpy(entry->vip, STRNULL(argv[ARG_IP], "0.0.0.0"), sizeof (entry->vip));
2926  }
2927 
2928  if (argc > ARG_HOSTNAME) {
2929  strlcpy(entry->hostname, STRNULL(argv[ARG_HOSTNAME], "unknown"),
2930  sizeof (entry->hostname));
2931  strlcpy(entry->vhostname, STRNULL(argv[ARG_HOSTNAME], "unknown"),
2932  sizeof (entry->vhostname));
2933  }
2934 
2935  if (argc > ARG_FROM) {
2936  strlcpy(entry->from, STRNULL(argv[ARG_FROM], "nullsender"),
2937  sizeof (entry->from));
2938  strlcpy(entry->vfrom, STRNULL(argv[ARG_FROM], "nullsender"),
2939  sizeof (entry->vfrom));
2940  }
2941 
2942  if (argc > ARG_RESOLVE) {
2943  entry->resolve = strcasecmp(argv[ARG_RESOLVE], "RESOLVE_OK") == 0;
2944  }
2945 
2946  if (argc > ARG_COUNT) {
2947  int t;
2948 
2949  errno = 0;
2950  t = (time_t) zeStr2ulong(argv[ARG_COUNT], NULL, 0);
2951  if (errno == 0)
2952  entry->count = t;
2953  }
2954 
2955  FREE(tstr);
2956 
2957  return TRUE;
2958 }
2959 
2960 static bool
2961 grey_value_entry2str(s, entry, sz)
2962  char *s;
2963  grey_entry_T *entry;
2964  size_t sz;
2965 {
2966  if (s == NULL || sz == 0 || entry == NULL)
2967  return FALSE;
2968 
2969  if (entry->date_init == (time_t) 0)
2970  entry->date_init = time(NULL);
2971  if (entry->date_updt == (time_t) 0)
2972  entry->date_updt = time(NULL);
2973 
2974  memset(s, 0, sz);
2975 #if 1
2976  snprintf(s, sz, "%ld;%ld;%s;%s;%s;%s;%d;%s",
2977 #else
2978  snprintf(s, sz, "%ld:%ld:%s:%s:%s:%s:%d:%s",
2979 #endif
2980  entry->date_init,
2981  entry->date_updt,
2982  entry->ip,
2983  entry->hostname,
2984  STRBOOL(ISNULLSENDER(entry->from), "nullsender", entry->from),
2985  "FLAGS", entry->count < 1 ? 1 : entry->count, "NULL");
2986 
2987  return TRUE;
2988 }
2989 
2990 #if 0
2991 static void
2992 grey_entry_value(s, size, date_init, date_updt, ip, hostname, from, to, count,
2993  resolve)
2994  char *s;
2995  size_t size;
2996  time_t date_init;
2997  time_t date_updt;
2998  char *ip;
2999  char *hostname;
3000  char *from;
3001  char *to;
3002  int count;
3003  bool resolve;
3004 {
3005  if (s == NULL || size == 0)
3006  return;
3007 
3008  snprintf(s, size, "%ld:%ld:%s:%s:%s:%d:%s",
3009  date_init,
3010  date_updt,
3011  ip,
3012  hostname,
3013  STRBOOL(ISNULLSENDER(from), "nullsender", from),
3014  count < 1 ? 1 : count, STRBOOL(resolve, "RESOLVE_OK", "RESOLVE_KO"));
3015 }
3016 
3017 #endif
3018 
3019 /* ****************************************************************************
3020  * *
3021  * *
3022  **************************************************************************** */
3023 
3024 /*
3025 ** Server
3026 ** Remove entries
3027 ** add entries
3028 **
3029 ** Don't whitelist IP
3030 **
3031 */
3032 bool
3033 grey_remove(where, key)
3034  int where;
3035  char *key;
3036 {
3037 
3038  return TRUE;
3039 }
3040 
3041 /* ****************************************************************************
3042  * *
3043  * *
3044  **************************************************************************** */
3045 int
3047  int which;
3048 {
3049 
3050  switch (which) {
3051  case GDB_NONE:
3052  break;
3053  case GDB_PENDING:
3054  return gdata.nbp;
3055  break;
3056  case GDB_VALID:
3057  return gdata.nbv;
3058  break;
3059  case GDB_WHITELIST:
3060  return gdata.nbw;
3061  break;
3062  case GDB_BLACKLIST:
3063  return gdata.nbb;
3064  break;
3065  case GDB_ALL:
3066  break;
3067  }
3068 
3069  return -1;
3070 }
3071 
3072 /* ****************************************************************************
3073  * *
3074  * *
3075  **************************************************************************** */
3076 
3077 #define DOM_DIM 32
3078 
3079 #define SECLEVDOMAINS {"com","org","co","asso","net","gov","edu",NULL}
3080 
3081 static bool recursive_compatible_domainnames(char *da, char *db,
3082  int level);
3083 
3084 static bool
3085 compatible_domainnames(da, db)
3086  char *da;
3087  char *db;
3088 {
3089  return recursive_compatible_domainnames(da, db, 0);
3090 }
3091 
3092 #define DOM_DIM 32
3093 
3094 #define SECLEVDOMAINS {"com","org","co","asso","net","gov","edu",NULL}
3095 
3096 static bool
3097 recursive_compatible_domainnames(da, db, level)
3098  char *da;
3099  char *db;
3100  int level;
3101 {
3102  bool ok = TRUE;
3103  char *ta, *tb;
3104  char *p;
3105 
3106  if (!grey_compat_domain_check)
3107  goto end;
3108 
3109  ta = tb = NULL;
3110 
3111  if (da == NULL || db == NULL)
3112  goto end;
3113 
3114  if (strchr(da, '[') != NULL || strchr(da, ']') != NULL) {
3115  ok = FALSE;
3116  goto end;
3117  }
3118  if (strchr(db, '[') != NULL || strchr(db, ']') != NULL) {
3119  ok = FALSE;
3120  goto end;
3121  }
3122 
3123  if ((ta = strdup(da)) == NULL) {
3124  ZE_LogSysError("strdup() error");
3125  goto error;
3126  }
3127 
3128  if ((tb = strdup(db)) == NULL) {
3129  ZE_LogSysError("strdup() error");
3130  goto error;
3131  }
3132 
3133  (void) zeStrRev(ta);
3134  (void) zeStrRev(tb);
3135 
3136  if ((p = strchr(ta, '@')) != NULL)
3137  *p = '\0';
3138 
3139  if ((p = strchr(tb, '@')) != NULL)
3140  *p = '\0';
3141 
3142  /*
3143  * if (ta != NULL && tb != NULL)
3144  */
3145  {
3146  int argca, argcb, m;
3147  char *argva[DOM_DIM], *argvb[DOM_DIM];
3148  int nbe = 0;
3149 
3150  ok = FALSE;
3151 
3152  argca = zeStr2Tokens(ta, DOM_DIM, argva, ".");
3153  argcb = zeStr2Tokens(tb, DOM_DIM, argvb, ".");
3154 
3155  m = MIN(argca, argcb);
3156 
3157  if (m > 1) {
3158  for (nbe = 0; nbe < m; nbe++)
3159  if (strcasecmp(argva[nbe], argvb[nbe]) != 0)
3160  break;
3161 
3162  switch (nbe) {
3163  case 0:
3164  if (strcasecmp(argva[1], argvb[1]) == 0)
3165  ok = TRUE;
3166  break;
3167  case 1:
3168  break;
3169  case 2:
3170  {
3171  char *seclev[] = SECLEVDOMAINS;
3172  char **p = seclev;
3173 
3174  ok = TRUE;
3175  for (p = seclev; *p != NULL; p++) {
3176  if (strcasecmp(argva[1], *p) == 0) {
3177  ok = FALSE;
3178  break;
3179  }
3180  }
3181  }
3182  break;
3183  default:
3184  ok = TRUE;
3185  break;
3186  }
3187  }
3188  }
3189 
3190  if (++level > 2)
3191  goto end;
3192 
3193  if (!ok) {
3194  char buf[256];
3195  int argc;
3196  char *argv[32];
3197  int i;
3198 
3199  memset(buf, 0, sizeof (buf));
3200  if (lookup_policy("GreyEquivDomain", da, buf, sizeof (buf), FALSE)) {
3201  if (strlen(buf) > 0) {
3202  argc = zeStr2Tokens(buf, 32, argv, ", ");
3203  for (i = 0; i < argc; i++) {
3204  ok = recursive_compatible_domainnames(db, argv[i], level);
3205  if (ok)
3206  break;
3207  }
3208  }
3209  }
3210  if (ok)
3211  goto end;
3212 
3213  memset(buf, 0, sizeof (buf));
3214  if (lookup_policy("GreyEquivDomain", db, buf, sizeof (buf), FALSE)) {
3215  if (strlen(buf) > 0) {
3216  argc = zeStr2Tokens(buf, 32, argv, ", ");
3217  for (i = 0; i < argc; i++) {
3218  ok = recursive_compatible_domainnames(da, argv[i], level);
3219  if (ok)
3220  break;
3221  }
3222  }
3223  }
3224  }
3225 
3226  goto end;
3227 
3228 error:
3229  ZE_LogSysError("strdup() error");
3230 
3231 end:
3232  FREE(ta);
3233  FREE(tb);
3234 
3235  return ok;
3236 }
#define GREY_DW_NULLSENDER
Definition: ze-grey.h:55
LISTR_T * zeLinkedList_Add(LISTR_T *, char *, int, void *, size_t)
Definition: zeLinkedList.c:34
#define GREY_EMAIL_FULL
Definition: ze-grey.h:42
#define MAX(a, b)
Definition: macros.h:139
Definition: ze-ipv6.h:32
bool sd_printf(int sd, char *format,...)
Definition: ze-inet.c:629
#define GREY_DW_NONE
Definition: ze-grey.h:54
time_t date_init
Definition: ze-grey.c:300
Definition: ze-grey.c:299
#define GREY_CRIT_LOCK()
Definition: ze-grey.c:275
bool zeDb_Unlock(ZEDB_T *h)
Database unlock.
Definition: zeDb.c:907
#define STRBOOL(x, t, f)
Definition: macros.h:87
char vfrom[256]
Definition: ze-grey.c:313
char * zeStrRev(char *)
Definition: zeStrings.c:34
#define GDB_PENDING
Definition: ze-grey.h:66
void grey_set_compat_domain_check(bool enable)
Definition: ze-grey.c:473
bool grey_set_cleanup_interval(time_t tclean)
Definition: ze-grey.c:459
char * to
Definition: ze-grey.c:287
bool zeDb_AddRec(ZEDB_T *h, char *, void *, size_t)
Definition: zeDb.c:750
bool zeLinkedList_Clear(LISTR_T *, LISTCLEAR_F)
Definition: zeLinkedList.c:195
#define strrchr
Definition: ze-sys.h:219
#define ZE_FUNCTION
Definition: ze-sys.h:471
ZEDB_T gdbv
Definition: ze-grey.c:113
#define GREY_DW_SPAMTRAP
Definition: ze-grey.h:59
bool zeDb_OK(ZEDB_T *h)
Definition: zeDb.c:649
bool grey_set_tuples(char *ip, char *from, char *to)
Definition: ze-grey.c:355
#define GREY_ARGS
Definition: ze-grey.h:72
#define FREE(x)
Definition: macros.h:37
#define SECLEVDOMAINS
Definition: ze-grey.c:3094
#define BF_SZ
Definition: ze-grey.c:35
char * from
Definition: ze-grey.c:286
#define ARG_DATE_INIT
Definition: ze-grey.h:73
#define STRNULL(x, r)
Definition: macros.h:81
#define GDB_WHITELIST
Definition: ze-grey.h:68
int count
Definition: zeLinkedList.h:41
char * key
Definition: zeLinkedList.h:38
#define GREY_TP_MIN_NORM
Definition: ze-grey.c:48
bool grey_set_delays(time_t tp_min_norm, time_t tp_max_norm, time_t tp_min_null, time_t tp_max_null)
Definition: ze-grey.c:399
#define ZE_LogMsgInfo(level,...)
Definition: zeSyslog.h:110
#define GDB_BLACKLIST
Definition: ze-grey.h:69
Definition: zeDb.h:47
#define IPV6_ADDR_REGEX
Definition: macros.h:219
long nkt
Definition: ze-grey.c:1869
#define FALSE
Definition: macros.h:160
#define DB_BTREE_SEQ_START()
Definition: zeDb.h:176
#define ST_DONE
Definition: ze-grey.c:2494
#define strlcpy
Definition: zeString.h:32
#define ZE_LogMsgError(level,...)
Definition: zeSyslog.h:113
bool zeDb_CursorGetFirst(ZEDB_T *h, char *, size_t, void *, size_t)
Definition: zeDb.c:1041
bool grey_remove_entry(char *which, char *key)
Definition: ze-grey.c:1019
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
#define STREQUAL(a, b)
Definition: macros.h:78
#define GREY_ADDR_NET
Definition: ze-grey.h:48
#define GREY_ERROR
Definition: ze-grey.h:38
char * extract_email_address(char *, char *, size_t)
#define OPT_YES
Definition: ze-cf.h:45
bool zeDb_DelRec(ZEDB_T *h, char *)
Definition: zeDb.c:863
ZEDB_ENV_T * work_db_env
Definition: ze-databases.c:30
#define ARG_IP
Definition: ze-grey.h:75
#define ARG_RESOLVE
Definition: ze-grey.h:78
#define GREY_TP_MAX_NULL
Definition: ze-grey.c:57
int grey_check(char *kAddr, char *kFrom, char *kRcpt, char *kName, bool *new, bool can_validate)
Definition: ze-grey.c:491
#define GREY_TP_MAX_NORM
Definition: ze-grey.c:54
time_t date_updt
Definition: ze-grey.c:301
#define MIN_CNT_PER_DOMAIN
Definition: ze-grey.c:44
int cf_get_int(int id)
Definition: ze-cf.c:803
#define TIMER_INIT(t)
Definition: ze-grey.c:1853
int zeStr2Tokens(char *, int, char **, char *)
Definition: zeStrings.c:610
#define MIN(a, b)
Definition: macros.h:140
#define strlcat
Definition: zeString.h:28
#define strchr
Definition: ze-sys.h:218
#define GREY_DW_BAD_RCPT
Definition: ze-grey.h:60
void grey_launch_thread()
Definition: ze-grey.c:1747
#define GREY_TV_MAX
Definition: ze-grey.c:61
bool lookup_policy(char *, char *, char *, size_t, bool)
Definition: ze-policy.c:51
bool zeDb_Open(ZEDB_T *h, ZEDB_ENV_T *, char *, int, bool, bool, size_t)
Definition: zeDb.c:462
bool ipv6_str2rec(ipv6_T *ipv6, char *sin)
Definition: ze-ipv6.c:96
ZEDB_T gdbp
Definition: ze-grey.c:111
int grey_validate(char *kAddr, char *kFrom, char *kRcpt, char *kName)
Definition: ze-grey.c:825
#define GREY_DW_BAD_MX
Definition: ze-grey.h:61
#define ISNULLSENDER(x)
Definition: ze-grey.c:341
#define ARG_HOSTNAME
Definition: ze-grey.h:76
#define ST_WHITE
Definition: ze-grey.c:2492
bool zeDb_Close(ZEDB_T *h)
Definition: zeDb.c:667
#define GDB_ALL
Definition: ze-grey.h:70
#define DT_GREY_INTERVAL
Definition: ze-grey.c:41
#define DB_BTREE_SEQ_END()
Definition: zeDb.h:196
#define GREY_CRIT_UNLOCK()
Definition: ze-grey.c:276
#define ST_IDLE
Definition: ze-grey.c:2489
#define GREY_TW_MAX
Definition: ze-grey.c:64
bool grey_set_lifetime(time_t tv, time_t tw, time_t tb)
Definition: ze-grey.c:422
#define GREY_OK
Definition: ze-grey.h:35
#define DOM_DIM
Definition: ze-grey.c:3092
#define GREY_DW_ALL
Definition: ze-grey.h:63
int grey_upload(char *fname, char *which)
Definition: ze-grey.c:2774
long nke
Definition: ze-grey.c:1870
int count
Definition: ze-grey.c:315
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
bool grey_init(char *workdir, bool rd, int mode)
Definition: ze-grey.c:1326
void log_grey_expire(char *)
Definition: ze-log-grey.c:75
char * database
Definition: zeDb.h:50
int nb
Definition: ze-connopen.c:61
char * ip
Definition: ze-grey.c:285
#define GREY_STANDALONE
Definition: ze-grey.h:50
bool zeDb_GetRec(ZEDB_T *h, char *, void *, size_t)
Definition: zeDb.c:791
char * extract_host_from_email_address(char *, char *, size_t)
char vip[256]
Definition: ze-grey.c:311
char key[3 *BF_SZ]
Definition: ze-grey.c:1868
#define ARG_DATE_UPDT
Definition: ze-grey.h:74
#define TRUE
Definition: macros.h:157
#define GREY_EMAIL_USER
Definition: ze-grey.h:43
#define CF_LOG_GREY_CLEANING
Definition: cfh-defs.h:62
#define ZE_MessageWarning(level,...)
Definition: zeSyslog.h:92
#define GREY_ADDR_NONE
Definition: ze-grey.h:46
LISTR_T * next
Definition: zeLinkedList.h:37
#define ST_PENDING
Definition: ze-grey.c:2490
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
#define ZE_LogSysWarning(...)
Definition: zeSyslog.h:128
bool grey_check_bad_smtp_client(char *ip, uint32_t flags)
char from[256]
Definition: ze-grey.c:305
#define GREY_ADDR_FULL
Definition: ze-grey.h:47
bool zeDb_CursorOpen(ZEDB_T *h, bool)
Definition: zeDb.c:936
void grey_close()
Definition: ze-grey.c:1381
char vrcpt[256]
Definition: ze-grey.c:314
#define ARG_FROM
Definition: ze-grey.h:77
#define GREY_TB_MAX
Definition: ze-grey.c:67
int zeDb_errno(ZEDB_T *h)
Definition: zeDb.c:922
#define SIGTID
Definition: ze-grey.c:1740
char rcpt[256]
Definition: ze-grey.c:306
#define STREMPTY(x, r)
Definition: macros.h:82
#define GREY_EMAIL_HOST
Definition: ze-grey.h:44
time_t last
Definition: ze-connopen.c:60
char vhostname[256]
Definition: ze-grey.c:312
#define GREY_WAIT
Definition: ze-grey.h:36
void grey_set_dewhite_flags(char *s, bool reset)
Definition: ze-grey.c:1772
bool zeDb_CursorDel(ZEDB_T *h)
Definition: zeDb.c:1189
#define T_EXPIRE_BAD_MIN
Definition: ze-grey.c:71
#define TIMER_LOG(s, t)
Definition: ze-grey.c:1860
#define TIMER_NOW(t)
Definition: ze-grey.c:1858
char * key
Definition: ze-grey.c:290
ZEDB_T gdbb
Definition: ze-grey.c:117
#define GREY_EMAIL_NONE
Definition: ze-grey.h:41
#define DB_BTREE_SEQ_CHECK(key, dbname)
Definition: zeDb.h:182
#define GREY_DW_DOMAIN_MISMATCH
Definition: ze-grey.h:57
bool grey_set_max_pending(int nbnormal, int nbnull)
Definition: ze-grey.c:442
#define DT_GREY_SLEEP
Definition: ze-grey.c:38
#define GREY_DW_BAD_CLIENT
Definition: ze-grey.h:58
#define MINUTES
Definition: macros.h:143
void * data
Definition: zeLinkedList.h:39
#define HOURS
Definition: macros.h:144
#define ST_BLACK
Definition: ze-grey.c:2493
#define GDB_VALID
Definition: ze-grey.h:67
bool zeDb_CursorClose(ZEDB_T *h)
Definition: zeDb.c:991
#define GREY_TP_MIN_NULL
Definition: ze-grey.c:51
#define T_EXPIRE_VALID_BAD_MAX
Definition: ze-grey.c:77
#define GREY_DW_BAD_RESOLVE
Definition: ze-grey.h:56
time_t date
Definition: ze-grey.c:289
#define STRCASEEQUAL(a, b)
Definition: macros.h:72
unsigned long zeStr2ulong(char *s, int *error, unsigned long dval)
Definition: zeStrConvert.c:100
ZEDB_T gdbw
Definition: ze-grey.c:115
int grey_dbcount(int which)
Definition: ze-grey.c:3046
bool grey_remove_entries_from_file(char *which, char *fname)
Definition: ze-grey.c:1031
#define ARG_COUNT
Definition: ze-grey.h:79
char ip[256]
Definition: ze-grey.c:303
void ipv6_prefix_str(ipv6_T *addr, char *buf, size_t size, int n)
Definition: ze-ipv6.c:290
char hostname[256]
Definition: ze-grey.c:304
#define GDB_NONE
Definition: ze-grey.h:65
int grey_dump(int fd, char *which, time_t dt)
Definition: ze-grey.c:2685
#define ZEDB_INITIALIZER
Definition: zeDb.h:111
#define DAYS
Definition: macros.h:145
uint64_t timems_T
Definition: zeTime.h:32
long uint32_t
Definition: ze-sys.h:489
#define ST_VALID
Definition: ze-grey.c:2491
bool grey_reload()
Definition: ze-grey.c:1393
bool grey_remove(int where, char *key)
Definition: ze-grey.c:3033
bool zeDb_CursorGetNext(ZEDB_T *h, char *, size_t, void *, size_t)
Definition: zeDb.c:1116
char * hostname
Definition: ze-grey.c:288
bool zeDb_Flush(ZEDB_T *h)
Definition: zeDb.c:725
time_t zeStr2time(char *s, int *error, time_t dval)
Definition: zeStrConvert.c:291
#define DBG_LEVEL
Definition: ze-grey.c:279
#define T_EXPIRE_PENDING_BAD_MAX
Definition: ze-grey.c:74
bool resolve
Definition: ze-grey.c:316
bool zeDb_Lock(ZEDB_T *h)
Database lock.
Definition: zeDb.c:896