ze-filter  (ze-filter-0.8.0-develop-180218)
mlfi_eom.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 /* ****************************************************************************
26  * *
27  * *
28  ******************************************************************************/
29 static sfsistat eom_check_xfiles(SMFICTX * ctx, attachment_T * ahead,
30  bool * done);
31 static sfsistat eom_check_virus(SMFICTX * ctx, attachment_T * ahead,
32  bool * done);
33 static sfsistat eom_check_content(SMFICTX * ctx, bool * done);
34 
35 /* ****************************************************************************
36  * *
37  * *
38  ******************************************************************************/
39 #define LOG_NOCHECK(priv, reason) \
40  do { \
41  char bufh[512], buft[512]; \
42  char st[512]; \
43  char *pc; \
44  \
45  memset(bufh, 0, sizeof(bufh)); \
46  memset(st, 0, sizeof(st)); \
47  if (priv->peer_addr != NULL && strlen(priv->peer_addr) > 0) \
48  { \
49  snprintf(st, sizeof (st), ", PeerAddr=(%s)", priv->peer_addr); \
50  strlcat(bufh, st, sizeof (bufh)); \
51  } \
52  if (priv->peer_name != NULL && strlen(priv->peer_name) > 0) \
53  { \
54  snprintf(st, sizeof (st), ", PeerName=(%s)", priv->peer_name); \
55  strlcat(bufh, st, sizeof (bufh)); \
56  } \
57  \
58  pc = CTX_NETCLASS_LABEL(priv); \
59  if (pc != NULL && strlen(pc) > 0) \
60  { \
61  snprintf(st, sizeof (st), ", NetClass=(%s)", pc); \
62  strlcat(bufh, st, sizeof (bufh)); \
63  } \
64  if (priv->env_from != NULL && strlen(priv->env_from) > 0) \
65  { \
66  snprintf(st, sizeof (st), ", MAIL=(%s)", priv->env_from); \
67  strlcat(bufh, st, sizeof (bufh)); \
68  } \
69  \
70  { \
71  rcpt_addr_T *p; \
72  char buft[512]; \
73  int nr = 0; \
74  \
75  for (p = priv->env_rcpt; p != NULL; p = p->next) \
76  { \
77  nr++; \
78  \
79  if (p->access != RCPT_OK) \
80  continue; \
81  \
82  /* strlcpy(buft, bufh, sizeof (buft)); */ \
83  memset(buft, 0, sizeof(buft)); \
84  \
85  snprintf(st, sizeof (st), ", NbRCPT=(%d/%d)", \
86  nr, priv->env_nb_rcpt); \
87  strlcat(buft, st, sizeof (buft)); \
88  \
89  if (p->rcpt != NULL && strlen(p->rcpt) > 0) \
90  { \
91  snprintf(st, sizeof (st), ", RCPT=(%s)", p->rcpt); \
92  strlcat(buft, st, sizeof (buft)); \
93  } \
94  \
95  ZE_MessageInfo(10, "%s Content Unchecked by policy %s %s", \
96  CONNID_STR(priv->id), bufh, buft); \
97  } \
98  } \
99  } while (0)
100 
101 
102 /* ****************************************************************************
103  * *
104  * *
105  ******************************************************************************/
106 sfsistat
108  SMFICTX *ctx;
109 
110 {
111  CTXPRIV_T *priv = MLFIPRIV(ctx);
112  char hbuf[1024];
113  int result = SMFIS_CONTINUE;
114  attachment_T *ahead = NULL;
115  int nb_files = 0;
116  int nb_xfiles = 0;
117  char *log_msg = NULL;
118  char log_msg_buf[1024];
119 
120  time_t now = time(NULL);
121 
123  stats_inc(STAT_MSGS, 1);
124  if (priv == NULL)
125  return SMFIS_TEMPFAIL;
126 
128 
129  sm_macro_update(ctx, priv->sm);
130 
131  if (!spool_file_close(priv))
132  ZE_LogMsgWarning(0, "spool_file_close error");
133 
134  if (priv->rej_greyrcpt > 0) {
135  priv->rej_greymsgs++;
137  }
138 
139  priv->nb_msgs++;
140  (void) smtprate_add_entry(RATE_VOLUME, priv->peer_addr, priv->peer_name,
141  (priv->msg_size + 512) / 1024, now);
142 
143  /*
144  ** XXX : REM - The update of the number of messages shall be here
145  ** at eom callback or at mailfrom callback ?
146  */
147  (void) smtprate_add_entry(RATE_MSGS, priv->peer_addr, priv->peer_name, 1,
148  now);
149  {
150  bool addrPlusEmail = FALSE;
151  char *s = NULL;
152 
153  if ((s = getenv("FROMRATEFULL")) != NULL) {
154  if (zeStrRegex(s, "yes|oui|true", NULL, NULL, TRUE))
155  addrPlusEmail = TRUE;
156  }
157 
158  if (addrPlusEmail) {
159  char cbuf[256];
160 
161  snprintf(cbuf, sizeof (cbuf), "%s-%s", priv->peer_addr, priv->env_from);
162  (void) smtprate_add_entry(RATE_FROM_MSGS, cbuf, NULL, 1, now);
163  } else {
164  (void) smtprate_add_entry(RATE_FROM_MSGS, priv->env_from, NULL, 1, now);
165  }
166  }
167 
168  {
169  char *auth_authen = NULL;
170 
171  auth_authen = sm_macro_get_str(priv->sm, "{auth_authen}");
172  if (auth_authen != NULL && strlen(auth_authen) > 0) {
173  (void) smtprate_add_entry(RATE_AUTH_MSGS, auth_authen, NULL, 1, now);
174  }
175  }
176 
177  /*
178  * check for message size against limits
179  */
180  {
181  long limit = 0;
182  size_t fsize;
183 
184  limit =
185  check_limit_all_rcpts("MaxMsgSize", priv->peer_addr, priv->peer_name,
186  CTX_NETCLASS_LABEL(priv), priv->env_from,
187  priv->env_rcpt, 0);
188  if (limit > 0) {
189  fsize = zeGetFileSize(priv->fname);
190  if (fsize > limit) {
191  char msg[256];
192 
193  result = SMFIS_REJECT;
194  (void) jsmfi_setreply(ctx, "550", "5.7.1", MSG_SIZE_EXCEED_LIMIT);
195  snprintf(msg, sizeof (msg), "%s (%ld/%ld)", MSG_SIZE_EXCEED_LIMIT,
196  fsize, limit);
197  log_msg_context(ctx, msg);
198  }
199  }
200  }
201  if (result != SMFIS_CONTINUE)
202  goto fin;
203 
204  /*
205  ** Checking Delivery Notification Requests
206  */
207  if (IS_UNKNOWN(priv->netclass.class)) {
208  bool do_it;
209 
211 
212  char **hdr = NULL;
213 
214  char *unwanted_hdrs[] = {
215  "Disposition-Notification-To",
216  "X-Confirm-Reading-To",
217  "Generate-Delivery-Report",
218  "Disclose-Recipients",
219  NULL
220  };
221 
222  for (hdr = unwanted_hdrs; *hdr != NULL; hdr++) {
223  int nb = 0;
224  header_T *h = priv->headers;
225 
226  h = priv->headers;
227  while ((h = get_msgheader_next(h, *hdr)) != NULL) {
228  if (h->value == NULL)
229  continue;
230 
231  nb++;
232  log_msg_context(ctx, *hdr);
233  ZE_MessageInfo(10, "%s SPAM CHECK - %s : %s",
234  CONNID_STR(priv->id), *hdr, h->value);
235  }
236  if (do_it) {
237  while (nb > 0)
238  smfi_chgheader(ctx, *hdr, nb--, NULL);
239  }
240  }
241  }
242 
243  if (cf_get_int(CF_PRESENCE) == OPT_SHOW) {
244  char *p = NULL;
245  char *url;
246  char host[512];
247 
248  char *mac_srv_name = NULL;
249  char *mac_cl_addr = NULL;
250  char *mac_cl_ptr = NULL;
251  char *mac_cl_name = NULL;
252  char *mac_qid = NULL;
253 
254  memset(host, 0, sizeof (host));
255  if (!get_hostname(host, sizeof (host)))
256  snprintf(host, sizeof (host), "localhost");
257  /*
258  * add a header to the message announcing our presence
259  */
260  switch (cf_get_int(CF_ZE_HOSTNAME)) {
261  case OPT_SYSTEM:
262  break;
263  case OPT_SENDMAIL:
264  p = smfi_getsymval(ctx, "j");
265  break;
266  default:
268  break;
269  }
270 
271  if ((p != NULL) && (strlen(p) > 0))
272  strlcpy(host, p, sizeof (host));
273  url = cf_get_str(CF_FILTER_URL);
274  url = STRNULL(url, "");
275  if (strcasecmp(url, "http://foss.jose-marcio.org") == 0)
276  url = "http : // foss dot jose-marcio dot org";
277  if (strcasecmp(url, "NO") == 0)
278  url = "";
279  if (strlen(url) > 0) {
280  snprintf(hbuf, sizeof hbuf,
281  "at %s with ID %s by Joe's ze-filter (%s)!",
282  host, CONNID_STR(priv->id), url);
283  } else {
284  snprintf(hbuf, sizeof hbuf,
285  "at %s with ID %s by Joe's ze-filter !", host,
286  CONNID_STR(priv->id));
287  }
288  smfi_addheader(ctx, "X-Miltered", hbuf);
289 
290  mac_srv_name = sm_macro_get_str(priv->sm, "j");
291  mac_srv_name = STREMPTY(mac_srv_name, my_hostname);
292  mac_cl_addr = sm_macro_get_str(priv->sm, "{client_addr}");
293  mac_cl_addr = STREMPTY(mac_cl_addr, "null");
294  mac_cl_ptr = sm_macro_get_str(priv->sm, "{client_ptr}");
295  mac_cl_ptr = STREMPTY(mac_cl_ptr, "null");
296  mac_cl_name = sm_macro_get_str(priv->sm, "{client_name}");
297  mac_cl_name = STREMPTY(mac_cl_name, "null");
298  mac_qid = sm_macro_get_str(priv->sm, "i");
299  mac_qid = STREMPTY(mac_qid, "null");
300 
301  {
302  char *mac_auth_type = NULL;
303  char *mac_auth_authen = NULL;
304 
305  mac_auth_type = sm_macro_get_str(priv->sm, "{auth_type}");
306  mac_auth_authen = sm_macro_get_str(priv->sm, "{auth_authen}");
307 
308  if ((mac_auth_type != NULL) && (strlen(mac_auth_type) > 0) ||
309  (mac_auth_authen != NULL) && (strlen(mac_auth_authen) > 0)) {
310  snprintf(hbuf, sizeof (hbuf), "USER-ID %s",
311  STREMPTY(mac_auth_authen, "???"));
312  smfi_addheader(ctx, "X-ze-filter-Auth", hbuf);
313  }
314  }
315 
316  snprintf(hbuf, sizeof (hbuf),
317  "%s from %s/%s/%s/%s/%s",
318  CONNID_STR(priv->id),
319  mac_cl_name, mac_cl_ptr, mac_cl_addr,
320  priv->helohost, priv->env_from);
321 
322  smfi_addheader(ctx, "X-ze-filter-Envelope", hbuf);
323  }
324 
325  /*
326  ** remove old headers
327  **/
328  {
329  int argc;
330  char *argv[32];
331  char buf[512], *p = NULL;
332  int i, n;
333 
335  if (p != NULL)
336  strlcpy(buf, p, sizeof (buf));
337  else
338  memset(buf, 0, sizeof (buf));
339  argc = zeStr2Tokens(buf, 32, argv, ", ");
340  for (i = 0; i < argc; i++) {
341  if (strlen(argv[i]) == 0 || STRCASEEQUAL(argv[i], "none"))
342  break;
343 
344  n = count_msgheader_attr(priv->headers, argv[i]);
345  while (n > 0) {
346  (void) smfi_chgheader(ctx, argv[i], n, NULL);
347  n--;
348  }
349  }
350  }
351 
352  /*
353  ** remove old scores
354  */
355  {
356  int argc;
357  char *argv[32];
358  char buf[512], *p = NULL;
359  int n;
360 
362  if (p != NULL)
363  strlcpy(buf, p, sizeof (buf));
364  else
365  memset(buf, 0, sizeof (buf));
366  argc = zeStr2Tokens(buf, 32, argv, ", ");
367 
368  if (argc > 0) {
369  n = count_msgheader_attr(priv->headers, "x-ze-filter-score");
370  while (n > 0) {
371  bool do_it = FALSE;
372 
373  header_T *h;
374  int i;
375 
376  h = get_msgheader_index_2(priv->headers, "X-ze-filter-Score", n);
377  if (h == NULL)
378  break;
379  if (h->value == NULL || strlen(h->value) == 0)
380  continue;
381 
382  for (i = 0; i < argc; i++) {
383  char *arg = argv[i];
384  bool preserve = FALSE;
385  char expr[256];
386 
387  if (strlen(arg) == 0) {
388  do_it = FALSE;
389  break;
390  }
391  if (STRCASEEQUAL(arg, "none")) {
392  do_it = FALSE;
393  break;
394  }
395  if (STRCASEEQUAL(arg, "all")) {
396  do_it = TRUE;
397  break;
398  }
399 
400  if (*arg == '!') {
401  preserve = TRUE;
402  arg++;
403  }
404  if (strlen(arg) == 0) {
405  do_it = FALSE;
406  break;
407  }
408 
409 
410  /*
411  * "MSGID : %s on %s : ze-filter score : %s : %d/%d %d %5.3f -> %d",
412  */
413  snprintf(expr, sizeof (expr), "on [^ ]*%s : ze-filter score", arg);
414  if (zeStrRegex(h->value, expr, NULL, NULL, TRUE)) {
415  if (!preserve)
416  do_it = TRUE;
417  break;
418  }
419  }
420 
421  if (do_it)
422  (void) smfi_chgheader(ctx, "X-ze-filter-Score", n, NULL);
423 
424  n--;
425  }
426  }
427  }
428 
429  /*
430  ** Let's finish attached files name extraction
431  **
432  */
433  if (priv->tcontent.field_type != CT_NONE)
434  save_content_field(&priv->tcontent, &priv->lcontent);
435  if ((result == SMFIS_CONTINUE) && (priv->lcontent != NULL)) {
436  nb_files = extract_attachments(priv->lcontent, &ahead);
437  priv->nb_files += nb_files;
438  stats_inc(STAT_FILES, nb_files);
439  }
440 
441  /*
442  ** No message check before this point.
443  */
444 #if 0
445  /*
446  * Message with passport ???
447  */
448  if (priv->nb_rcpt == 1 && priv->pass_ok)
449  goto fin;
450 #endif
451 
452  /*
453  ** update bad recipients
454  */
455  if (result == SMFIS_CONTINUE) {
456  int n;
457 
458  if ((n = update_nb_badrcpts(ctx)) > 0)
459  ZE_MessageInfo(19, "%s : BAD RECIPIENTS : %d", CONNID_STR(priv->id), n);
460  priv->nb_mbadrcpt = n;
461  ZE_MessageInfo(19, "mlfi_eom : bad = %d", n);
462  result = check_nb_badrcpts(ctx);
463  if (result != SMFIS_CONTINUE)
464  priv->rej_badrcpt = TRUE;
465  }
466  if (result != SMFIS_CONTINUE)
467  goto fin;
468 
469  /*
470  ** Check for bad NULL SENDER : null sender with more than one recipient
471  */
472  if ((result == SMFIS_CONTINUE) && IS_UNKNOWN(priv->netclass.class)) {
474  if ((priv->env_nb_rcpt > 1) && (strstr(priv->env_from, "<>") != NULL)) {
475  result = SMFIS_REJECT;
476  (void) jsmfi_setreply(ctx, "550", "5.7.1", MSG_BAD_NULL_SENDER);
478  }
479  }
480  }
481  if (result != SMFIS_CONTINUE)
482  goto fin;
483 
484  /*
485  ** Check for empty messages or too short messages
486  */
487  if ((priv->body_nb == 0 || priv->msg_short)
488  && IS_UNKNOWN(priv->netclass.class)) {
489  char **cmd;
490  header_T *h = priv->headers;
491 
492  priv->msg_short = TRUE;
493  h = priv->headers;
494  while ((h = get_msgheader_next(h, "Subject")) != NULL) {
495  if (h->value == NULL)
496  continue;
497  for (cmd = SYMPA_CMDS; (*cmd != NULL); cmd++) {
498  ZE_MessageInfo(12, "Checking Subject %s %s", h->value, *cmd);
499  if (zeStrRegex(h->value, *cmd, NULL, NULL, TRUE)) {
500  priv->msg_short = FALSE;
501  break;
502  }
503  }
504  }
505  }
506 
507  if (priv->msg_short && IS_UNKNOWN(priv->netclass.class)) {
508  int nb;
509 
510  nb = livehistory_add_entry(priv->peer_addr, time(NULL), 1, LH_EMPTYMSGS);
511  ZE_MessageInfo(9, "%s Empty or too short message : %d bytes",
512  CONNID_STR(priv->id), priv->msg_size);
514  bool doit = FALSE;
515 
516  doit =
517  check_policy_all_rcpts("RejectShortMsgs", priv->peer_addr,
518  priv->peer_name, CTX_NETCLASS_LABEL(priv),
519  priv->env_from, priv->env_rcpt, TRUE,
520  OPT_DEFAULT);
521  if (doit) {
522  result = SMFIS_REJECT;
523  (void) jsmfi_setreply(ctx, "550", "5.7.1", MSG_EMPTY_MSG);
525  }
526  }
527 
528  if (nb > 0);
529  }
530 
531  if (result != SMFIS_CONTINUE)
532  goto fin;
533 
534 #if 0
535  /*
536  ** Check DomainKeys
537  */
538  dkresult = check_domainkeys(ctx);
539  if (dkresult ...) {
540 
541  }
542 
543  if (result != SMFIS_CONTINUE)
544  goto fin;
545 
546 #endif
547 
548 #if _FFR_MODULES
549  /*
550  ** ze-filter modules
551  **
552  */
553  if (do_module_callback(ctx, 0, &result))
554  goto fin;
555  if (result != SMFIS_CONTINUE)
556  goto fin;
557 #endif /* _FFR_MODULES */
558 
559 
560 #if 1
561  /*
562  **
563  */
564 #define DEFAULT_ORDER "XFILES,VIRUS,CONTENT"
565 
566  {
567  char buf[256];
568  char *argv[32];
569  int argc;
570  int i;
571 
572  char *env = getenv("ORDER_CHECKS");
573 
574  if (env == NULL || strlen(env) == 0)
575  env = DEFAULT_ORDER;
576  strlcpy(buf, env, sizeof (buf));
577 
578  argc = zeStr2Tokens(buf, 32, argv, " ,");
579  for (i = 0; i < argc; i++) {
580  bool done = FALSE;
581 
582  if (STRCASEEQUAL(argv[i], "xfiles"))
583  result = eom_check_xfiles(ctx, ahead, &done);
584  if (STRCASEEQUAL(argv[i], "virus"))
585  result = eom_check_virus(ctx, ahead, &done);
586  if (STRCASEEQUAL(argv[i], "content"))
587  result = eom_check_content(ctx, &done);
588  if (done || result != SMFIS_CONTINUE)
589  break;
590  }
591  }
592 
593 #endif
594 
595  if (result != SMFIS_CONTINUE)
596  goto fin;
597 
599  log_attached_files(CONNID_STR(priv->id), priv->peer_addr, ahead);
600 
601  {
602  int n;
603 
604  if ((n = update_nb_badrcpts(ctx)) > 0)
605  ZE_MessageInfo(19, "%s : BAD RECIPIENTS : %d", CONNID_STR(priv->id), n);
606  priv->nb_cbadrcpt += n;
607  priv->nb_mbadrcpt = 0;
608  ZE_MessageInfo(19, "mlfi_abort : bad = %d", n);
609  }
610 
611 fin:
612  /*
613  **
614  ** Let's log what we found ...
615  **
616  */
617  if (priv->save_msg)
618  log_quarantine(ctx, ahead);
619 
620  if ((0 && cf_get_int(CF_LOG_ATTACHMENTS) == OPT_YES) || (log_msg != NULL)) {
621  log_msg = STRNULL(log_msg, "*** ATTACHMENTS : ");
622  log_msg_context(ctx, log_msg);
623 #if 0
624  if (nb_files > 0) {
625  attachment_T *p;
626 
627  p = ahead;
628  while (p != NULL) {
629  char *serror;
630 
631  serror = STRBOOL(p->xfile, "SUSPECT ???", "CLEAN");
632  ZE_MessageInfo(10, "%s : **** (%-11s) : %-10s %-30s %s\n",
633  CONNID_STR(priv->id),
634  serror, STRNULL(p->disposition, ""),
635  STRNULL(p->mimetype, ""), STRNULL(p->name, ""));
636  p = p->next;
637  }
638  }
639 #endif
640  }
641 
642  /*
643  **
644  ** Everything is done ! Let's clean up the house !
645  **
646  */
647  if (ahead != NULL)
648  free_attachment_list(ahead);
649  ahead = NULL;
650  (void) mlfi_cleanup(ctx, FALSE);
652  return result;
653 }
654 
655 /* ****************************************************************************
656  * *
657  * *
658  ******************************************************************************/
659 static sfsistat
660 eom_check_xfiles(ctx, ahead, done)
661  SMFICTX *ctx;
662  attachment_T *ahead;
663  bool *done;
664 {
665  CTXPRIV_T *priv = MLFIPRIV(ctx);
666  sfsistat result = SMFIS_CONTINUE;
667  time_t now = 0;
668 
669  if (done != NULL)
670  *done = FALSE;
671 
672  if (cf_get_int(CF_XFILES) == OPT_OK)
673  return result;
674 
675  if (!shall_check_xfiles(ctx)) {
676  LOG_NOCHECK(priv, "XFiles unchecked by policy");
677  return result;
678  }
679 
680  now = time(NULL);
681  /*
682  **
683  ** Let's check attached files
684  **
685  */
686  {
687  attachment_T *p = NULL;
688  char str_action[64];
689  int nb_xfiles = 0;
690  int nb_files = 0;
691  char *log_msg = NULL;
692 
693  memset(str_action, 0, sizeof (str_action));
694  p = ahead;
695  while (p != NULL) {
696  memset(str_action, 0, sizeof (str_action));
697  if (!p->xfile)
698  p->xfile = check_xfiles(p->name, p->mimetype, priv->msg_size,
699  str_action, sizeof (str_action));
700  if (p->xfile
701  && (strlen(str_action) == 0 || !STRCASEEQUAL(str_action, "ok")))
702  nb_xfiles++;
703  p = p->next;
704  nb_files++;
705  }
706 
707  if (nb_files > 0) {
708  priv->nb_xfiles += nb_xfiles;
709  stats_inc(STAT_XFILES, nb_xfiles);
710  }
711 
712  /*
713  **
714  ** Is there any XFILE ?
715  **
716  */
717 
718  if (nb_xfiles > 0) {
719  /*
720  * remplacer corps du message
721  */
722  /*
723  * message de log
724  */
725  /*
726  * ajoute l'expediteur dans la liste des destinataires
727  */
728 
729  int res_action = cf_get_int(CF_XFILES);
730  smtp_reply_T reply;
731 
732  if (0) {
733  char *xstatus = NULL;
734 
735  xstatus = cf_get_str(CF_XSTATUS_HEADER);
736  if (xstatus == NULL || strlen(xstatus) == 0)
737  xstatus = "X-ze-filter-Status";
738  smfi_addheader(ctx, xstatus, "Spam HI");
739  }
740 
742  DO_QUARANTINE_MESSAGE(priv, WHY_XFILE, NULL);
743 
744  log_msg = MSG_SHORT_XFILE;
745  memset(&reply, 0, sizeof (reply));
746  jc_fill_reply(&reply, "550", "5.6.0", MSG_XFILE, SMFIS_REJECT);
747  if (strlen(str_action) > 0) {
748  if (STRCASEEQUAL(str_action, "ok")) {
749  res_action = OPT_OK;
750  goto fin;
751  }
752  if (STRCASEEQUAL(str_action, "reject")) {
753  res_action = OPT_REJECT;
754  goto do_action;
755  }
756  if (STRCASEEQUAL(str_action, "notify")) {
757  res_action = OPT_NOTIFY;
758  goto do_action;
759  }
760  if (STRCASEEQUAL(str_action, "discard")) {
761  res_action = OPT_DISCARD;
762  goto do_action;
763  }
764  if (STRCASEEQUAL(str_action, "x-header")) {
765  res_action = OPT_X_HEADER;
766  goto do_action;
767  }
768 #if 0
769  {
770  char buf[256];
771 
772  if (query_policy
773  ("XfilesAction", str_action, buf, sizeof (buf), FALSE)) {
774  int res = jc_string2reply(&reply, buf);
775  }
776  }
777 #endif
778  }
779 
780  do_action:
781 
782  switch (res_action) {
783  case OPT_REJECT:
784  if (done != NULL)
785  *done = TRUE;
786  log_msg_context(ctx, log_msg);
787  (void) jsmfi_setreply(ctx, reply.rcode, reply.xcode, reply.msg);
788  result = SMFIS_REJECT;
789  break; /* end of OPT_REJECT */
790  case OPT_NOTIFY:
791  if (done != NULL)
792  *done = TRUE;
793  log_msg_context(ctx, log_msg);
794  result = do_notify(ctx, ahead, NULL, MSG_XFILE, "XFILE");
795  break;
796  case OPT_DISCARD:
797  if (done != NULL)
798  *done = TRUE;
799  log_msg_context(ctx, log_msg);
800  result = SMFIS_DISCARD;
801  break; /* end of OPT_DISCARD */
802  case OPT_X_HEADER:
803  if (done != NULL)
804  *done = TRUE;
805  log_msg_context(ctx, log_msg);
806  {
807  char *tag = cf_get_str(CF_XFILE_SUBJECT_TAG);
808 
809  if (!add_tag2subject(ctx, tag))
810  ZE_LogMsgWarning(0, "Error changing subject");
811  }
812  result = SMFIS_CONTINUE;
813  break; /* end of OPT_X_HEADER */
814  default:
815  break;
816  }
817 
819  priv->peer_name, 1, now);
820  }
821  if (nb_xfiles > 0 || (done != NULL && *done))
822  log_attached_files(CONNID_STR(priv->id), priv->peer_addr, ahead);
823  }
824 
825 fin:
826  return result;
827 }
828 
829 /* ****************************************************************************
830  * *
831  * *
832  ******************************************************************************/
833 static sfsistat
834 eom_check_virus(ctx, ahead, done)
835  SMFICTX *ctx;
836  attachment_T *ahead;
837  bool *done;
838 {
839  CTXPRIV_T *priv = MLFIPRIV(ctx);
840  sfsistat result = SMFIS_CONTINUE;
841  char log_msg_buf[1024];
842 
843  if (done != NULL)
844  *done = FALSE;
846  return result;
847  if (!shall_check_virus(ctx)) {
848  LOG_NOCHECK(priv, "Virus unchecked by policy");
849  return result;
850  }
851 
852  memset(log_msg_buf, 0, sizeof (log_msg_buf));
853  /*
854  **
855  ** Let's do antivirus checking...
856  **
857  */
858  {
859  char question[JCOMBUFSZ];
860  char why[JCOMBUFSZ];
861  char data[JCOMBUFSZ];
862  int avres = AV_OK;
863  char *msg = NULL;
864 
865  memset(why, 0, sizeof (data));
866  memset(data, 0, sizeof (why));
867  strlcpy(question, priv->fname, sizeof (question));
868  avres = av_client(why, sizeof (why), data, sizeof (data), question);
869  ZE_MessageInfo(11, "av_client : %3d (%s) (%s)", avres, why,
870  zeStrChomp(question));
871 
872  if (avres == AV_ZERO || avres == AV_OK)
873  goto fin;
874 
875  if (avres == AV_ERROR) {
876  if (done != NULL)
877  *done = TRUE;
878  ZE_MessageError(9, "%s Error with external message scanner",
879  CONNID_STR(priv->id));
881  (void) jsmfi_vsetreply(ctx, "450", "4.6.0",
882  "Temporary system error. Come back later");
883  result = SMFIS_TEMPFAIL;
884  }
885  log_msg_context(ctx, "External Scanner Error");
886 
887  goto fin;
888  }
889 
890  switch (avres) {
891  case AV_VIRUS:
892  priv->nb_virus++;
893  stats_inc(STAT_VIRUS, 1);
894  FREE(priv->msg.virus);
895  priv->msg.virus = strdup(data);
896  log_virus(CONNID_STR(priv->id), priv->peer_addr, data);
897 
898  snprintf(log_msg_buf, sizeof (log_msg_buf), "%s : %s", MSG_VIRUS, data);
899  msg = MSG_VIRUS;
900 
901  priv->fsuffix = SUFFIX_VIRUS;
903  DO_QUARANTINE_MESSAGE(priv, WHY_VIRUS, NULL);
904  break;
905  case AV_POLICY:
906  priv->nb_policy++;
908 
909  snprintf(log_msg_buf, sizeof (log_msg_buf), "%s", MSG_SHORT_POLICY);
910  msg = MSG_POLICY;
911 
912  priv->fsuffix = SUFFIX_POLICY;
914  DO_QUARANTINE_MESSAGE(priv, WHY_POLICY, NULL);
915  break;
916  }
917 
918  switch (cf_get_int(CF_SCANNER_ACTION)) {
919  case OPT_REJECT:
920  if (done != NULL)
921  *done = TRUE;
922  (void) jsmfi_vsetreply(ctx, "550", "5.6.0", "%s : %s", msg, data);
923  result = SMFIS_REJECT;
924  break; /* end of OPT_REJECT */
925  case OPT_NOTIFY:
926  if (done != NULL)
927  *done = TRUE;
928  result = do_notify(ctx, ahead, data, msg, "VIRUS");
929  break;
930  case OPT_DISCARD:
931  if (done != NULL)
932  *done = TRUE;
933  result = SMFIS_DISCARD;
934  break; /* end of OPT_DISCARD */
935  case OPT_X_HEADER:
936  /*
937  * XXX add x-header
938  */
939  if (done != NULL)
940  *done = TRUE;
941  break;
942  default:
943  break;
944  }
945 
946  log_msg_context(ctx, log_msg_buf);
947  if (avres == AV_VIRUS)
948  log_attached_files(CONNID_STR(priv->id), priv->peer_addr, ahead);
949  }
950 
951 fin:
952  return result;
953 }
954 
955 
956 
957 /* ****************************************************************************
958  * *
959  * *
960  ******************************************************************************/
961 static sfsistat
962 eom_check_content(ctx, done)
963  SMFICTX *ctx;
964  bool *done;
965 {
966  CTXPRIV_T *priv = MLFIPRIV(ctx);
967  sfsistat result = SMFIS_CONTINUE;
968 
969  /*
970  **
971  ** Content check (anti-spam)
972  */
973  priv->netScores.bayes = 0.;
974  if (!shall_check_content(ctx)) {
975  LOG_NOCHECK(priv, "Content check disabled by policy");
976  return result;
977  }
978 
979  /*
980  ** Bayesian filter
981  */
983  bool check_it = TRUE;
984 
985  priv->rawScores.do_bayes = FALSE;
986  priv->rawScores.bayes = 0.;
987 
988  check_it = check_policy_all_rcpts("BayesCheck", priv->peer_addr,
989  priv->peer_name, CTX_NETCLASS_LABEL(priv),
990  priv->env_from,
991  priv->env_rcpt, TRUE, OPT_DEFAULT);
992 
993  if (!check_it) {
994  LOG_NOCHECK(priv, "Statistical filter disabled by policy");
995  }
996 
997  if (check_it) {
998  sfilter_vsm_T bcheck;
999  double score = 0;
1000 
1001  memset(&bcheck, 0, sizeof (bcheck));
1002  bcheck.nbt = cf_get_int(CF_BAYES_NB_TOKENS);
1003  if (bcheck.nbt <= 0)
1004  bcheck.nbt = 64;
1005  score = sfilter_check_message(CONNID_STR(priv->id), priv->fname, &bcheck);
1006  if (score >= 0.)
1007  ZE_MessageInfo(10, "%s Bayes filter score : %6.3f",
1008  CONNID_STR(priv->id), score);
1009  else
1010  ZE_MessageInfo(10, "%s Bayes filter score : Unchecked",
1011  CONNID_STR(priv->id));
1012  if (score >= 0.) {
1013  priv->rawScores.Bayes.value = score;
1014  priv->rawScores.Bayes.odds = logit(score);
1015  priv->rawScores.Bayes.actif = TRUE;
1016  priv->netScores.Bayes = priv->rawScores.Bayes;
1017 
1018  priv->netScores.bayes = score;
1019  priv->rawScores.bayes = score;
1020  priv->rawScores.do_bayes = TRUE;
1021 
1022  if (score >= BSCORE_HI)
1023  priv->nb_bspam++;
1024  if (score <= BSCORE_LO)
1025  priv->nb_bham++;
1026  } else {
1027  priv->rawScores.Bayes.value = 0.5;
1028  priv->rawScores.Bayes.odds = 0.;
1029  priv->rawScores.Bayes.actif = FALSE;
1030  priv->netScores.Bayes = priv->rawScores.Bayes;
1031 
1032  priv->netScores.bayes = 0.;
1033  priv->rawScores.bayes = 0.;
1034  priv->rawScores.do_bayes = FALSE;
1035  }
1036  }
1037  }
1038 
1040  bool check_it = TRUE;
1041  size_t fsize;
1042  size_t fsize_max = 300 KBYTES;
1043 
1044  {
1045  char *env;
1046 
1047  if ((env = getenv("LR_MAX_FSIZE")) != NULL)
1048  fsize_max = zeStr2size(env, NULL, fsize_max);
1049  }
1050  fsize = zeGetFileSize(priv->fname);
1051 
1052  ZE_MessageInfo(10, "%s LogReg filter sizes : size %7d, size max %7d %s %s",
1053  CONNID_STR(priv->id), fsize, fsize_max,
1054  (fsize >= fsize_max ? "XXX" : "---"),
1055  (fsize >= 300000 && fsize < fsize_max ? "YYY" : "---"));
1056 
1057  if (fsize < fsize_max)
1058  check_it = check_policy_all_rcpts("BayesCheck", priv->peer_addr,
1059  priv->peer_name,
1060  CTX_NETCLASS_LABEL(priv),
1061  priv->env_from,
1062  priv->env_rcpt, TRUE, OPT_DEFAULT);
1063  else
1064  check_it = FALSE;
1065 
1066  if (check_it) {
1067  test_score_T mscore, nscore;
1068  lr_cargs_T cargs;
1069  lr_margs_T margs;
1070 
1071  memset(&mscore, 0, sizeof (mscore));
1072  memset(&cargs, 0, sizeof (cargs));
1073  memset(&margs, 0, sizeof (margs));
1074 
1075  if (lr_classify(CONNID_STR(priv->id), priv->fname, NULL, NULL, &mscore));
1076 
1077  priv->rawScores.LogReg = priv->netScores.LogReg = mscore;
1078  {
1079  char buf[256];
1080  double gres = 0.;
1081  bool agree = TRUE;
1082  int win;
1083 
1084  nscore.value = 0.;
1085  nscore.odds = 0.;
1086  nscore.actif = FALSE;
1087 
1088  agree = TRUE;
1089  ZE_MessageInfo(10, "%s LogReg filter score : %6.3f",
1090  CONNID_STR(priv->id), priv->rawScores.LogReg.value);
1091 
1092  if (priv->rawScores.Bayes.actif && priv->rawScores.LogReg.actif) {
1093 #define KLOGBAY (2./3.)
1094 #define MLOGBAY (2.)
1095  double odds = 0;
1096 
1097 #if 1
1098  double Mlb = 2.;
1099  double Klb = 2. / 3.;
1100  double BLogit, LLogit;
1101 
1102  if (Mlb < 0) {
1103  char *s = getenv("MLOGBAY");
1104 
1105  if (s != NULL) {
1106  Mlb = zeStr2double(s, NULL, MLOGBAY);
1107  if (Mlb < 0)
1108  Mlb = MLOGBAY;
1109  } else
1110  Mlb = MLOGBAY;
1111  }
1112  if (Klb < 0) {
1113  char *s = getenv("KLOGBAY");
1114 
1115  if (s != NULL) {
1116  Klb = zeStr2double(s, NULL, KLOGBAY);
1117  if (Klb < 0. || Klb > 1.)
1118  Klb = KLOGBAY;
1119  } else
1120  Klb = KLOGBAY;
1121  }
1122 
1123  LLogit = (Mlb * Klb) * logit(priv->rawScores.LogReg.value);
1124  BLogit = (Mlb * (1 - Klb)) * logit(priv->rawScores.Bayes.value);
1125 
1126  agree = (SIGN(BLogit) == SIGN(LLogit));
1127  win = SIGN(fabs(BLogit) - fabs(LLogit));
1128  odds = BLogit + LLogit;
1129  gres = logitinv(odds);
1130 #else
1131  odds = ((2. / 3.) * logit(priv->rawScores.Bayes.value) +
1132  (4. / 3.) * logit(priv->rawScores.LogReg.value));
1133  gres = logitinv((2. / 3.) * logit(priv->rawScores.Bayes.value) +
1134  (4. / 3.) * logit(priv->rawScores.LogReg.value));
1135  agree = (SIGN(priv->rawScores.Bayes.value - 0.5) ==
1136  SIGN(priv->rawScores.LogReg.value - 0.5));
1137  win = SIGN(fabs(priv->rawScores.Bayes.value - 0.5) -
1138  fabs(priv->rawScores.LogReg.value - 0.5));
1139 #endif
1140  nscore.value = gres;
1141  nscore.odds = odds;
1142  nscore.actif = TRUE;
1143  }
1144  if (priv->rawScores.Bayes.actif && !priv->rawScores.LogReg.actif) {
1145  gres = priv->rawScores.Bayes.value;
1146  nscore = priv->rawScores.Bayes;
1147 
1148  nscore.value = gres;
1149  nscore.odds = logit(gres);
1150  nscore.actif = TRUE;
1151  }
1152  if (!priv->rawScores.Bayes.actif && priv->rawScores.LogReg.actif) {
1153  gres = priv->rawScores.LogReg.value;
1154  nscore = priv->rawScores.LogReg;
1155 
1156  nscore.value = gres;
1157  nscore.odds = logit(gres);
1158  nscore.actif = TRUE;
1159  }
1160 
1161  if (priv->rawScores.Bayes.actif || priv->rawScores.LogReg.actif) {
1162  priv->rawScores.bayes = gres;
1163  priv->rawScores.do_bayes = TRUE;
1164  priv->netScores.bayes = gres;
1165  priv->netScores.do_bayes = TRUE;
1166  }
1167 
1168  priv->rawScores.Global = priv->netScores.Global = nscore;
1169 
1170  snprintf(buf, sizeof (buf), "%s B=%.5f L=%.5f G=%.5f %-8s %s%s",
1171  CONNID_STR(priv->id),
1172  priv->rawScores.Bayes.value,
1173  priv->rawScores.LogReg.value,
1174  gres,
1175  STRBOOL(agree, "Agree", "Disagree"),
1176  STRBOOL(agree, "", STRBOOL(win > 0, "Winner=B", "Winner=P")),
1177  STRBOOL(agree, "", STRBOOL(gres > 0.5, "S", "H")));
1178 
1179  ZE_MessageInfo(10, buf);
1180 
1181  smfi_addheader(ctx, "X-Scores-Stats", buf);
1182 
1183  /*
1184  * Active Learning
1185  */
1186  if (fabs(priv->rawScores.LogReg.value - 0.5) < 0.35) {
1187  smfi_addheader(ctx, "X-Label-Query", "YES");
1188  }
1189  }
1190  }
1191  }
1192 
1193  /*
1194  ** Message contents : oracle, URLBL and pattern matching
1195  */
1196  {
1197  bool do_regex, do_oracle, do_urlbl;
1198 
1199  do_regex = (cf_get_int(CF_SPAM_REGEX) != OPT_NO);
1200  do_oracle = (cf_get_int(CF_SPAM_ORACLE) != OPT_NO);
1201  do_urlbl = (cf_get_int(CF_SPAM_URLBL) != OPT_NO);
1202 
1203  priv->rawScores.do_regex = do_regex;
1204  priv->rawScores.do_oracle = do_oracle;
1205  priv->rawScores.do_urlbl = do_urlbl;
1206 
1207  if (do_regex || do_oracle || do_urlbl)
1208  result = check_msg_contents(ctx);
1209  else
1210  LOG_NOCHECK(priv, "Content check disabled by policy");
1211 
1212  }
1213 
1214  /*
1215  ** Appel a la routine de decision de score
1216  */
1217  {
1218  bool do_log = FALSE;
1219 
1220  result = evaluate_message_score(ctx, &do_log);
1221  if (do_log && ze_logLevel >= 8) {
1222  char logbuf[256];
1223 
1224  snprintf(logbuf, sizeof (logbuf), "%s : B=%.3f U=%d R=%d O=%d -> G=%.3f",
1225  "Content Check",
1226  priv->rawScores.bayes, priv->rawScores.urlbl,
1227  priv->rawScores.body + priv->rawScores.headers,
1228  priv->rawScores.oracle, priv->rawScores.combined);
1229 
1230  log_msg_context(ctx, logbuf);
1231  }
1232  }
1233 
1234  {
1235  char *env = getenv("DUMP_MESSAGE_SCORE");
1236 
1237  if (env != NULL && STRCASEEQUAL(env, "yes"))
1238  dump_msg_scores4stats(ctx);
1239  }
1240 
1241 
1242  (void) smtprate_add_entry(RATE_SCORE, priv->peer_addr, priv->peer_name,
1243  (int) (100 * priv->rawScores.combined), time(NULL));
1244  (void) smtprate_add_entry(RATE_SPAM, priv->peer_addr, priv->peer_name,
1245  priv->rawScores.bayes > BSCORE_HI ? 1 : 0,
1246  time(NULL));
1247  (void) smtprate_add_entry(RATE_HAM, priv->peer_addr, priv->peer_name,
1248  priv->rawScores.bayes < BSCORE_LO ? 1 : 0,
1249  time(NULL));
1250 
1251 fin:
1252  return result;
1253 }
#define CF_REMOVE_HEADERS
Definition: cfh-defs.h:139
#define MSG_EMPTY_MSG
Definition: ze-reply.h:109
#define OPT_SHOW
Definition: ze-cf.h:55
#define OPT_DEFAULT
Definition: ze-cf.h:79
int smtprate_add_entry(int, char *, char *, int, time_t)
Definition: ze-smtprate.c:363
double combined
Definition: ze-msg-score.h:73
rcpt_addr_T * env_rcpt
double sfilter_check_message(char *id, char *fname, sfilter_vsm_T *bcheck)
Definition: ze-bcheck.c:328
#define CF_XFILE_SUBJECT_TAG
Definition: cfh-defs.h:95
sfsistat check_nb_badrcpts(SMFICTX *)
char * virus
header_T * get_msgheader_index_2(header_T *, char *, int)
Definition: ze-headers.c:221
#define STRBOOL(x, t, f)
Definition: macros.h:87
#define OPT_DISCARD
Definition: ze-cf.h:50
#define CF_LOG_ATTACHMENTS
Definition: cfh-defs.h:59
msg_scores_T rawScores
test_score_T Bayes
Definition: ze-msg-score.h:96
bool check_policy_all_rcpts(char *prefix, char *ip, char *name, char *netclass, char *from, rcpt_addr_T *rcpt, bool result, int conflict)
Definition: ze-policy.c:470
void free_attachment_list(attachment_T *)
Definition: ze-mimelist.c:218
char * fname
void stats_inc(int, long)
Definition: ze-stats.c:401
#define WHY_POLICY
Definition: ze-spool.h:30
bool shall_check_xfiles(SMFICTX *)
#define CF_REJECT_SHORT_BODIES
Definition: cfh-defs.h:178
#define CF_PRESENCE
Definition: cfh-defs.h:32
#define WHY_XFILE
Definition: ze-spool.h:28
#define SMFIS_TEMPFAIL
#define CF_SCANNER_SAVE
Definition: cfh-defs.h:103
int jsmfi_setreply(SMFICTX *, char *, char *, char *)
Definition: ze-libmilter.c:99
sfsistat mlfi_cleanup(SMFICTX *ctx, bool ok)
Definition: mlfi_cleanup.c:31
#define FREE(x)
Definition: macros.h:37
#define MSG_SHORT_POLICY
Definition: ze-reply.h:239
bool add_tag2subject(SMFICTX *, char *)
#define MSG_SIZE_EXCEED_LIMIT
Definition: ze-reply.h:141
#define AV_POLICY
Definition: ze-avclient.h:35
char * peer_addr
int ze_logLevel
Definition: zeSyslog.c:34
#define STRNULL(x, r)
Definition: macros.h:81
int check_domainkeys(SMFICTX *ctx)
#define AV_VIRUS
Definition: ze-avclient.h:34
sfsistat do_notify(SMFICTX *, attachment_T *, char *, char *, char *)
#define RATE_XFILES
Definition: ze-smtprate.h:58
bool lr_classify(char *id, char *fname, lr_cargs_T *cargs, lr_margs_T *margs, test_score_T *score)
Definition: ze-lr-funcs.c:965
#define CF_BAYES_NB_TOKENS
Definition: cfh-defs.h:109
#define CF_ZE_HOSTNAME
Definition: cfh-defs.h:31
#define CF_XFILES
Definition: cfh-defs.h:92
#define OPT_NOTIFY
Definition: ze-cf.h:49
#define CF_SPAM_ORACLE
Definition: cfh-defs.h:123
#define FALSE
Definition: macros.h:160
bool jc_fill_reply(smtp_reply_T *, char *, char *, char *, int)
size_t zeGetFileSize(char *)
Definition: zeFileTools.c:132
#define SMFIS_CONTINUE
#define SMFIS_REJECT
#define strlcpy
Definition: zeString.h:32
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
#define RATE_VOLUME
Definition: ze-smtprate.h:59
#define CF_REJECT_BAD_NULL_SENDER
Definition: cfh-defs.h:173
#define OPT_YES
Definition: ze-cf.h:45
#define STAT_MSGS
Definition: ze-stats.h:28
#define CF_SCANNER_REJECT_ON_ERROR
Definition: cfh-defs.h:101
#define DEFAULT_ORDER
bool dump_msg_scores4stats(SMFICTX *ctx)
bool shall_check_content(SMFICTX *)
bool lr_filter_ok
Definition: ze-lr-init.c:38
#define MSG_SHORT_XFILE
Definition: ze-reply.h:211
#define STAT_XFILES
Definition: ze-stats.h:34
bool shall_check_virus(SMFICTX *)
#define AV_ERROR
Definition: ze-avclient.h:33
bool spool_file_close(CTXPRIV_T *)
Definition: ze-spool.c:222
#define STAT_GREY_MSGS
Definition: ze-stats.h:80
#define CF_XSTATUS_HEADER
Definition: cfh-defs.h:131
char * zeStrChomp(char *)
Definition: zeStrings.c:501
int cf_get_int(int id)
Definition: ze-cf.c:803
#define MLFIPRIV(ctx)
int zeStr2Tokens(char *, int, char **, char *)
Definition: zeStrings.c:610
#define CF_BAYESIAN_FILTER
Definition: cfh-defs.h:105
#define INIT_CALLBACK(p, which)
Definition: ze-filter.c:125
#define DO_QUARANTINE_MESSAGE(priv, why, suffix)
#define RATE_AUTH_MSGS
Definition: ze-smtprate.h:67
sfsistat check_msg_contents(SMFICTX *)
#define KBYTES
Definition: macros.h:151
#define CF_REMOVE_SCORES
Definition: cfh-defs.h:140
#define SUFFIX_VIRUS
Definition: ze-spool.h:38
char my_hostname[]
Definition: ze-filter.c:89
#define OPT_REJECT
Definition: ze-cf.h:48
#define STAT_VIRUS
Definition: ze-stats.h:35
#define OPT_OK
Definition: ze-cf.h:47
#define KLOGBAY
void sm_macro_update(SMFICTX *, sm_mac_T *)
Definition: ze-smmacros.c:150
#define CF_SCANNER_ACTION
Definition: cfh-defs.h:97
CONNID_T id
#define RATE_HAM
Definition: ze-smtprate.h:55
unsigned long msg_size
content_field_T tcontent
#define AV_OK
Definition: ze-avclient.h:32
int jsmfi_vsetreply(SMFICTX *ctx, char *ca, char *cb, char *format,...)
Definition: ze-libmilter.c:149
#define BSCORE_LO
Definition: ze-msg-score.h:33
#define OPT_SYSTEM
Definition: ze-cf.h:58
size_t zeStr2size(char *s, int *error, size_t dval)
Definition: zeStrConvert.c:237
#define INIT_CALLBACK_DELAY()
Definition: ze-filter.c:135
#define WHY_VIRUS
Definition: ze-spool.h:29
#define OPT_X_HEADER
Definition: ze-cf.h:51
#define STAT_POLICY
Definition: ze-stats.h:58
double zeStr2double(char *s, int *error, double dval)
Definition: zeStrConvert.c:202
#define LOG_NOCHECK(priv, reason)
Definition: mlfi_eom.c:39
long check_limit_all_rcpts(char *prefix, char *ip, char *name, char *netclass, char *from, rcpt_addr_T *rcpt, long defval)
Definition: ze-policy.c:660
char * value
Definition: ze-headers.h:36
int extract_attachments(content_field_T *, attachment_T **)
Definition: ze-mimelist.c:330
test_score_T LogReg
Definition: ze-msg-score.h:97
#define JCOMBUFSZ
Definition: ze-filter.h:184
#define IS_UNKNOWN(class)
Definition: ze-netclass.h:51
char * fsuffix
void log_virus(char *, char *, char *)
Definition: ze-log-virus.c:71
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
int nb
Definition: ze-connopen.c:61
#define LH_EMPTYMSGS
#define OPT_NO
Definition: ze-cf.h:44
sfsistat mlfi_eom(SMFICTX *ctx)
Definition: mlfi_eom.c:107
#define RATE_SPAM
Definition: ze-smtprate.h:56
#define RATE_MSGS
Definition: ze-smtprate.h:54
#define SMFIS_DISCARD
#define TRUE
Definition: macros.h:157
#define MSG_POLICY
Definition: ze-reply.h:93
double value
Definition: ze-msg-score.h:67
bool get_hostname(char *, size_t)
Definition: ze-inet.c:181
content_field_T * save_content_field(content_field_T *, content_field_T **)
Definition: ze-mimelist.c:116
#define CF_XFILE_SAVE_MSG
Definition: cfh-defs.h:94
test_score_T Global
Definition: ze-msg-score.h:103
#define ZE_MessageError(level,...)
Definition: zeSyslog.h:93
#define SIGN(x)
Definition: macros.h:91
#define CF_DROP_DELIVERY_NOTIFICATION_REQUEST
Definition: cfh-defs.h:180
content_field_T * lcontent
char * cf_get_str(int id)
Definition: ze-cf.c:854
double logitinv(double x)
Definition: ze-logit.c:78
header_T * headers
#define CT_NONE
Definition: ze-scanmail.h:31
double bayes
Definition: ze-msg-score.h:88
#define STREMPTY(x, r)
Definition: macros.h:82
char * mimetype
Definition: ze-mimelist.h:72
#define STAT_FILES
Definition: ze-stats.h:33
char * peer_name
#define ZE_LogMsgWarning(level,...)
Definition: zeSyslog.h:112
#define CTX_NETCLASS_LABEL(priv)
msg_scores_T netScores
char * env_from
bool log_attached_files(char *, char *, attachment_T *)
Definition: ze-log-files.c:72
void log_quarantine(SMFICTX *, attachment_T *)
#define RATE_SCORE
Definition: ze-smtprate.h:57
bool do_module_callback(SMFICTX *ctx, int step, int *result)
Definition: ze-mod-tools.c:84
char * helohost
sm_mac_T * sm
#define SUFFIX_POLICY
Definition: ze-spool.h:39
char msg[256]
int count_msgheader_attr(header_T *, char *)
Definition: ze-headers.c:116
#define MLOGBAY
#define BSCORE_HI
Definition: ze-msg-score.h:35
#define CONNID_STR(connid)
Definition: ze-filter.h:113
#define MSG_XFILE
Definition: ze-reply.h:57
#define CHECK_CALLBACK_DELAY()
Definition: ze-filter.c:146
int update_nb_badrcpts(SMFICTX *)
#define STRCASEEQUAL(a, b)
Definition: macros.h:72
bool rej_badrcpt
#define CF_SPAM_REGEX
Definition: cfh-defs.h:116
bool check_xfiles(char *, char *, size_t, char *, size_t)
Definition: ze-fileexp.c:625
netclass_T netclass
sfsistat evaluate_message_score(SMFICTX *ctx, bool *)
#define CF_FILTER_URL
Definition: cfh-defs.h:34
int livehistory_add_entry(char *, time_t, int, int)
#define RATE_FROM_MSGS
Definition: ze-smtprate.h:63
#define MSG_VIRUS
Definition: ze-reply.h:89
#define CALLBACK_EOM
Definition: ze-callback.h:36
char * name
Definition: ze-mimelist.h:70
char * sm_macro_get_str(sm_mac_T *, char *)
Definition: ze-smmacros.c:191
void log_msg_context(SMFICTX *ctx, char *why)
struct attachment_T * next
Definition: ze-mimelist.h:74
#define AV_ZERO
Definition: ze-avclient.h:31
int jc_string2reply(smtp_reply_T *, char *)
#define OPT_SENDMAIL
Definition: ze-cf.h:59
double logit(double p)
Definition: ze-logit.c:34
int msg[MAX_SCORE+2]
Definition: ze-stats.c:41
#define CF_SPAM_URLBL
Definition: cfh-defs.h:113
header_T * get_msgheader_next(header_T *, char *)
Definition: ze-headers.c:175
int av_client(char *, size_t, char *, size_t, char *)
Definition: ze-avclient.c:316
char * disposition
Definition: ze-mimelist.h:71
#define MSG_BAD_NULL_SENDER
Definition: ze-reply.h:191