ze-filter  (ze-filter-0.8.0-develop-180218)
ze-callbacklogs.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 : Mon Nov 15 23:13:14 CET 2004
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 #include <ze-sys.h>
27 #include <ze-filter.h>
28 #include <ze-filter-data.h>
29 #include <ze-callbacklogs.h>
30 #include <ze-spool.h>
31 
32 /* ****************************************************************************
33  * *
34  * *
35  ******************************************************************************/
36 #define ADDROKTOANSWER(x) ((strlen(STRNULL(x)) != 0) && (strcmp(NULLSENDER,x) != 0))
37 
38 bool
40  char *p;
41 {
42  if ((p == NULL) || (strlen(p) == 0))
43  return FALSE;
44 
45  if (strcmp(NULLSENDER, p) == 0)
46  return FALSE;
47 
48  return TRUE;
49 }
50 
51 /* ****************************************************************************
52  * *
53  * *
54  ******************************************************************************/
55 sfsistat
56 do_notify(ctx, ahead, answer, why, tag)
57  SMFICTX *ctx;
58  attachment_T *ahead;
59  char *answer;
60  char *why;
61  char *tag;
62 {
63  CTXPRIV_T *priv = MLFIPRIV(ctx);
64  char *msg;
65  bool warn_send = FALSE;
66  bool warn_rcpt = FALSE;
67 
68  warn_send = (cf_get_int(CF_NOTIFY_SENDER) == OPT_YES);
69  warn_rcpt = (cf_get_int(CF_NOTIFY_RCPT) == OPT_YES);
70 
71  if (!warn_send && !warn_rcpt)
72  return SMFIS_DISCARD;
73 
74  if (!warn_rcpt) {
75  rcpt_addr_T *p = priv->env_rcpt;
76 
77  while (p != NULL) {
78  if (p->rcpt != NULL)
79  smfi_delrcpt(ctx, p->rcpt);
80  p = p->next;
81  }
82  }
83 
84  if (warn_send) {
85  char *p = NULL;
86 
87  if (check_address_ok2warn(priv->env_from)) {
88  p = priv->env_from;
89  } else {
91  p = priv->hdr_from;
92  }
93 
94  if (p != NULL)
95  smfi_addrcpt(ctx, p);
96  else
97  warn_send = FALSE;
98  }
99 
100  if (!warn_send && !warn_rcpt)
101  return SMFIS_DISCARD;
102 
103  if ((msg = (char *) malloc(WARN_MSG_SIZE)) != NULL) {
104  char buf[256];
105 
106  /*
107  * Content-Type: mutipart/report; report-type=delivery-status
108  */
109  smfi_chgheader(ctx, "Content-type", 1, NULL);
110  smfi_chgheader(ctx, "Content-disposition", 1, NULL);
111  smfi_chgheader(ctx, "Content-transfer-encoding", 1, NULL);
112 
113 #if 1
114  snprintf(buf, sizeof (buf), "<%s.%04X.ze-filter@%s>", CONNID_STR(priv->id),
115  priv->nb_msgs, my_hostname);
116  smfi_chgheader(ctx, "Message-ID", 1, buf);
117  ZE_MessageInfo(10, "%s changing Message-ID header to %s",
118  CONNID_STR(priv->id), buf);
119 #endif
120 
122  char *sender = cf_get_str(CF_ZE_SENDER);
123 
124  if ((sender != NULL) && (strlen(sender) > 0))
125  smfi_chgheader(ctx, "From", 1, sender);
126  }
127 
128  Smfi_ChgFrom(ctx, "<>", NULL);
129 
131  char *subject = cf_get_str(CF_ZE_SUBJECT);
132 
133  if ((subject != NULL) && (strlen(subject) > 0))
134  smfi_chgheader(ctx, "Subject", 1, subject);
135  }
136  memset(msg, 0, WARN_MSG_SIZE);
137  read_error_msg(msg, WARN_MSG_SIZE, ahead, answer, priv->env_from, why, tag,
138  priv);
139  if (smfi_replacebody(ctx, (unsigned char *) msg, strlen(msg)) != 0)
140  ZE_LogMsgError(0, "Erreur replacing Body Message");
141  } else
142  ZE_LogSysError("Error malloc ing msg buf");
143 
144  FREE(msg);
145 
146  return SMFIS_CONTINUE;
147 }
148 
149 /* ****************************************************************************
150  * *
151  * *
152  ******************************************************************************/
153 
154 void
155 read_error_msg(buf, sz, ahead, answer, from, why, tag, priv)
156  char *buf;
157  int sz;
158  attachment_T *ahead;
159  char *answer;
160  char *from;
161  char *why;
162  char *tag;
163  CTXPRIV_T *priv;
164 {
165  FILE *fin;
166  char line[JCOMBUFSZ];
167  char s1[JCOMBUFSZ];
168 
169  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
170 
171  char *fname;
172  char path[1024];
173  char *cfdir = NULL;
174 
175  cfdir = cf_get_str(CF_CONFDIR);
176  if (cfdir == NULL || strlen(cfdir) == 0)
177  cfdir = ZE_CONFDIR;
178 
179  fname = cf_get_str(CF_ERROR_MSG_FILE);
180  ADJUST_FILENAME(path, fname, cfdir, ZE_ERROR_MSG_FILE);
181 
182  MUTEX_LOCK(&mutex);
183 
184  *buf = '\0';
185  if ((fin = fopen(path, "r")) != NULL) {
186  regex_t re;
187  regmatch_t pm;
188  bool compile_ok;
189  int state = 0;
190 
191  char tag_begin[256];
192  char tag_end[256];
193 
194  snprintf(tag_begin, sizeof (tag_begin), "<%s>", tag);
195  snprintf(tag_end, sizeof (tag_end), "</%s>", tag);
196  compile_ok = !regcomp(&re, "_+[A-Z]+_+", REG_ICASE | REG_EXTENDED);
197 
198  while (((strlen(buf) + sizeof (line)) < sz) &&
199  (fgets(line, sizeof (line), fin) != NULL)) {
200 
201  char *p = line + strlen(line) - 1;
202 
203  if (*p == '\n')
204  *p = '\0';
205  strcat(line, CRLF);
206 
207  if (state == 0) {
208  p = line + strspn(line, " \t");
209  if (*p == '#')
210  continue;
211 
212  if (strstr(line, tag_begin) == NULL)
213  continue;
214  state = 1;
215  continue;
216  } else {
217  if (strstr(line, tag_end) != NULL)
218  break;
219  }
220 
221  if (compile_ok && !regexec(&re, line, 1, &pm, 0)) {
222  char *p = s1;
223 
224  /*
225  * int len = pm.rm_eo - pm.rm_so;
226  */
227  int j;
228 
229  for (j = pm.rm_so; j < pm.rm_eo; j++) {
230  if (line[j] != '_')
231  *p++ = line[j];
232  }
233  *p = '\0';
234  if (strcasecmp(s1, "MSGID") == 0) {
235  char filename[256];
236  char *suffix = STRNULL(priv->fsuffix, SUFFIX_UNKNOWN);
237 
238  if (priv->fname == NULL)
239  continue;
240 
241  /*
242  * delete directory part from filename
243  */
244  if (zeMyBasename(filename, priv->fname, sizeof (filename)) == filename)
245  snprintf(line, sizeof (line), " **** MSG ID : %s%s", filename,
246  suffix);
247  else
248  snprintf(line, sizeof (line), " **** MSG ID : %s%s", priv->fname,
249  suffix);
250 
251  strcat(buf, line);
252  strcat(buf, CRLF);
253  continue;
254  }
255  if (strcasecmp(s1, "FROM") == 0) {
256 #if 1
257  from = STRNULL(priv->hdr_from, priv->env_from);
258  from = STRNULL(from, "Unknown sender");
259 #else
260  from = priv->env_from ? priv->env_from : "???";
261 #endif
262  snprintf(line, sizeof (line), " **** From : %s", from);
263  strcat(buf, line);
264  strcat(buf, CRLF);
265  continue;
266  }
267  if (strcasecmp(s1, "TO") == 0) {
268  char *to = NULL;
269 
270  if (priv != NULL)
271  to = priv->hdr_to;
272  to = STRNULL(to, "???");
273  snprintf(line, sizeof (line), " **** To : %s", to);
274  strcat(buf, line);
275  strcat(buf, CRLF);
276  continue;
277  }
278  if (strcasecmp(s1, "SUBJECT") == 0) {
279  char *p;
280 
281  p = priv->hdr_subject != NULL ? priv->hdr_subject : "-- NULL --";
282  snprintf(line, sizeof (line), " **** Subject : %s", p);
283  strlcat(buf, line, sz);
284  strlcat(buf, CRLF, sz);
285  continue;
286  }
287  if (strcasecmp(s1, "SMTP-PEER") == 0) {
288  char *p;
289 
290  p = priv->peer_name != NULL ? priv->peer_name : priv->peer_addr;
291  snprintf(line, sizeof (line), " **** Peer : %s", p);
292  strlcat(buf, line, sz);
293  strlcat(buf, CRLF, sz);
294  continue;
295  }
296  if (strcasecmp(s1, "WHY") == 0) {
297  strlcpy(line, why, sizeof (line));
298  strlcat(buf, line, sz);
299  strlcat(buf, CRLF, sz);
300  continue;
301  }
302  if (strcasecmp(s1, "VIRUS") == 0) {
303  snprintf(line, sizeof (line), " VIRUS FOUND : %s",
304  answer ? answer : "NONE");
305  strlcat(buf, line, sz);
306  strlcat(buf, CRLF, sz);
307  continue;
308  }
309  if (strcasecmp(s1, "TO") == 0)
310  continue;
311  if (strcasecmp(s1, "ATTACHMENT") == 0 && ahead != NULL) {
312  attachment_T *p = ahead;
313  int nb = 0;
314 
315  if (p == NULL) {
316  snprintf(line, sizeof (line),
317  " There isn't attached files !!!");
318  strlcat(buf, line, sz);
319  strlcat(buf, CRLF, sz);
320  continue;
321  }
322  while (p != NULL) {
323  char *serror;
324 
325  serror = STRBOOL(p->xfile, "SUSPECT", "CLEAN");
326  snprintf(line, sizeof (line), " **** (%-11s) : %s", serror,
327  p->name);
328  strlcat(buf, line, sz);
329  strlcat(buf, CRLF, sz);
330  if (p->mimetype != NULL) {
331  sprintf(line, " TYPE : %s", p->mimetype);
332  strlcat(buf, line, sz);
333  strlcat(buf, CRLF, sz);
334  }
335  p = p->next;
336  }
337  if (nb > 0) {
338  strlcat(buf, CRLF, sz);
339  snprintf(line, sizeof (line), " **** SUSPECT FILES : %d", nb);
340  strlcat(buf, line, sz);
341  strlcat(buf, CRLF, sz);
342  }
343  continue;
344  }
345  } else
346  strlcat(buf, line, sz);
347  }
348  fclose(fin);
349  regfree(&re);
350  if (state == 0)
351  ZE_LogMsgError(0, "read_error_msg : msg for tag %s not found",
352  STRNULL(tag, ""));
353  } else {
354  char *s = "";
355 
356  ZE_LogSysError("Error opening %s file", STRNULL(path, ""));
357 
358  s = "\n"
359  " This message was verified by the filtering system of our mail server.\n"
360  "\n"
361  "Original message was replaced by this one by the following reason :\n"
362  "\n"
363  "*** A suspicious file (executable code) was found in the message !\n"
364  "\n";
365 
366  strlcpy(buf, s, sz);
367  }
368 
369  /*
370  * Let's add a copyright footer
371  */
372  if (cf_get_int(CF_FOOTER) == OPT_SHOW) {
373  char s[128];
374  char *msg =
375  "ze-filter - (c) Ecole des Mines de Paris 2002, ...";
376 
377  zeStrSet(s, '-', 64);
378  strlcat(buf, s, sz);
379  strlcat(buf, CRLF, sz);
380  zeStrCenter(s, msg, 64);
381  strlcat(buf, s, sz);
382  strlcat(buf, CRLF CRLF, sz);
383  }
384  MUTEX_UNLOCK(&mutex);
385 }
386 
387 /* ****************************************************************************
388  * *
389  * *
390  ******************************************************************************/
391 static void
392 strlcpy_replace(out, in, sz, except, replace)
393  char *out;
394  char *in;
395  size_t sz;
396  char *except;
397  char replace;
398 {
399  char *p;
400 
401  if (in != out)
402  strlcpy(out, in, sz);
403  if (strchr(except, replace) != NULL)
404  replace = ' ';
405  while ((p = strpbrk(out, except)) != NULL)
406  *p = replace;
407 }
408 
409 void
411  SMFICTX *ctx;
412  char *why;
413 {
414  CTXPRIV_T *priv = MLFIPRIV(ctx);
415  char *smid = NULL;
416  char *id = NULL;
417 
418  char buf[1024];
419  char st[1024];
420  char stc[1024];
421  char *pc = NULL;
422 
423  if (priv == NULL)
424  return;
425 
426  id = CONNID_STR(priv->id);
427  if (id == NULL || strlen(id) == 0)
428  id = "NOID";
429 
430  smid = priv->sm_msgid;
431  smid = STRNULL(smid, "NOID");
432  why = STRNULL(why, "UNKNOWN");
433 
434  memset(buf, 0, sizeof (buf));
435  memset(st, 0, sizeof (st));
436 
437  strlcpy(buf, st, sizeof (buf));
438 
439  snprintf(buf, sizeof (buf), "%12s : SMQID=(%s)", id, smid);
440 
441  if (1) {
442  snprintf(st, sizeof (st), ", Txn#=(%d)", priv->nb_from);
443  strlcat(buf, st, sizeof (buf));
444  }
445 
446  pc = callback_name(priv->callback_id);
447  if (pc != NULL && strlen(pc) > 0) {
448  snprintf(st, sizeof (st), ", Callback=(%s)", pc);
449  strlcat(buf, st, sizeof (buf));
450  }
451 
452  {
453  char *name, *port, *addr;
454 
455  name = sm_macro_get_str(priv->sm, "{daemon_name}");
456  name = STRNULL(name, "*");
457  addr = sm_macro_get_str(priv->sm, "{if_addr}");
458  if (addr == NULL)
459  addr = sm_macro_get_str(priv->sm, "{daemon_addr}");
460  addr = STRNULL(addr, "*");
461  port = sm_macro_get_str(priv->sm, "{daemon_port}");
462  port = STRNULL(port, "*");
463 
464  snprintf(st, sizeof (st), ", Daemon=(%s;%s;%s)", name, addr, port);
465  strlcat(buf, st, sizeof (buf));
466  }
467 
468  if (why != NULL) {
469  snprintf(st, sizeof (st), ", Why=(%s)", why);
470  strlcat(buf, st, sizeof (buf));
471  }
472 
473  if (priv->peer_addr != NULL && strlen(priv->peer_addr) > 0) {
474  snprintf(st, sizeof (st), ", PeerAddr=(%s)", priv->peer_addr);
475  strlcat(buf, st, sizeof (buf));
476  }
477 
478  if (priv->peer_name != NULL && strlen(priv->peer_name) > 0) {
479  snprintf(st, sizeof (st), ", PeerName=(%s)", priv->peer_name);
480  strlcat(buf, st, sizeof (buf));
481  }
482 
483  pc = CTX_NETCLASS_LABEL(priv);
484  if (pc != NULL && strlen(pc) > 0) {
485  snprintf(st, sizeof (st), ", NetClass=(%s)", pc);
486  strlcat(buf, st, sizeof (buf));
487  }
488 #if 0
489  if (priv->callback_id == CALLBACK_EHLO || priv->callback_id == CALLBACK_MAIL)
490 #endif
491  {
492  if (priv->helohost != NULL && strlen(priv->helohost) > 0) {
493  snprintf(st, sizeof (st), ", Ehlo=(%s)", priv->helohost);
494  strlcat(buf, st, sizeof (buf));
495  }
496  }
497 
498  if (priv->env_from != NULL && strlen(priv->env_from) > 0) {
499  snprintf(st, sizeof (st), ", MAIL=(%s)", priv->env_from);
500  strlcat(buf, st, sizeof (buf));
501  }
502 
503  if (priv->callback_id == CALLBACK_RCPT) {
504  snprintf(st, sizeof (st), ", NbRCPT=(%d)", priv->env_nb_rcpt);
505  strlcat(buf, st, sizeof (buf));
506 
507  snprintf(st, sizeof (st), ", RCPT=(%s)", STRNULL(priv->env_to, "NULL"));
508  strlcat(buf, st, sizeof (buf));
509  }
510 
511  if (priv->callback_id <= CALLBACK_RCPT) {
512 #if 0
513  pc = NULL;
514  switch (reply) {
515  case SMFIS_CONTINUE:
516  pc = "continue";
517  break;
518  case SMFIS_TEMPFAIL:
519  pc = "tempfail";
520  break;
521  case SMFIS_REJECT:
522  pc = "reject";
523  break;
524  case SMFIS_ACCEPT:
525  pc = "accept";
526  break;
527  }
528 #endif
529  if (priv->reply_code != NULL) {
530  snprintf(st, sizeof (st), ", Reply=(%s)", priv->reply_code);
531  strlcat(buf, st, sizeof (buf));
532  }
533  ZE_MessageNotice(8, "%s", buf);
534 
535  goto fin;
536  }
537 
538  if (priv->callback_id > CALLBACK_RCPT) {
539  rcpt_addr_T *p;
540  char sbuf[1024];
541  int nr = 0;
542 
543  for (p = priv->env_rcpt; p != NULL; p = p->next) {
544  nr++;
545 
546  if (p->access != RCPT_OK)
547  continue;
548 
549  strlcpy(sbuf, buf, sizeof (sbuf));
550 
551  snprintf(st, sizeof (st), ", NbRCPT=(%d/%d)", nr, priv->env_nb_rcpt);
552  strlcat(sbuf, st, sizeof (sbuf));
553 
554  if (p->rcpt != NULL && strlen(p->rcpt) > 0) {
555  snprintf(st, sizeof (st), ", RCPT=(%s)", p->rcpt);
556  strlcat(sbuf, st, sizeof (sbuf));
557  }
558 
559  if (priv->hdr_from != NULL && strlen(priv->hdr_from) > 0) {
560  unsigned char *p = (unsigned char *) priv->hdr_from;
561  char *q;
562 
563  while (*p != '\0') {
564  if (*p > 0x7F || *p < 0x20)
565  *p = '.';
566  p++;
567  }
568 
569  while ((q = strchr(priv->hdr_from, '[')) != NULL)
570  *q = '\'';
571  while ((q = strchr(priv->hdr_from, ']')) != NULL)
572  *q = '\'';
573 
574  snprintf(st, sizeof (st), ", HeaderFrom=(%s)", priv->hdr_from);
575  strlcat(sbuf, st, sizeof (sbuf));
576  }
577 
578  if (priv->hdr_mailer != NULL && strlen(priv->hdr_mailer) > 0) {
579  unsigned char *p = (unsigned char *) priv->hdr_mailer;
580  char *q;
581 
582  while (*p != '\0') {
583  if (*p > 0x7F || *p < 0x20)
584  *p = '.';
585  p++;
586  }
587 
588 #if 0
589  while ((q = strchr(priv->hdr_mailer, '[')) != NULL)
590  *q = '\'';
591  while ((q = strchr(priv->hdr_mailer, ']')) != NULL)
592  *q = '\'';
593 
594  snprintf(st, sizeof (st), ", Mailer=(%s)", priv->hdr_mailer);
595 #else
596  strlcpy(stc, priv->hdr_mailer, sizeof (stc));
597  strlcpy_replace(stc, stc, sizeof (stc), "[]", '\'');
598  strlcpy_replace(stc, stc, sizeof (stc), "()", '.');
599  snprintf(st, sizeof (st), ", Mailer=(%s)", stc);
600 #endif
601 
602  strlcat(sbuf, st, sizeof (sbuf));
603  }
604 
605  if (priv->callback_id == CALLBACK_EOM) {
606 #if 0
607  int gScore = 0;
608  int iscore = 0;
609 
610  extern int combine_scores(msg_scores_T *);
611 
612  if (priv->rawScores.do_bayes)
613  gScore = combine_scores(&priv->netScores);
614  else
615  gScore = priv->netScores.body + priv->netScores.headers +
616  priv->netScores.oracle + priv->netScores.urlbl;
617 
618  iscore =
619  priv->netScores.body + priv->netScores.headers +
620  priv->netScores.oracle + priv->netScores.urlbl;
621 #endif
622  if (priv->rawScores.spam) {
623  snprintf(st, sizeof (st),
624  ", Scores=(R=%d U=%d O=%d B=%5.3f -> %6.3f)",
625  priv->rawScores.body + priv->rawScores.headers,
626  priv->rawScores.urlbl, priv->rawScores.oracle,
627  priv->rawScores.bayes, priv->rawScores.combined);
628  strlcat(sbuf, st, sizeof (sbuf));
629  }
630  }
631 
632  if (priv->msg_size >= 0) {
633  snprintf(st, sizeof (st), ", Size=(%ld)", priv->msg_size);
634  strlcat(sbuf, st, sizeof (sbuf));
635  }
636 
637  if (priv->reply_code != NULL) {
638  snprintf(st, sizeof (st), ", Reply=(%s)", priv->reply_code);
639  strlcat(sbuf, st, sizeof (sbuf));
640  }
641 
642  if (priv->save_msg) {
643  snprintf(st, sizeof (st), ", QuarantineFile=(%s)",
644  STRNULL(priv->fname, "NOFILE"));
645  strlcat(sbuf, st, sizeof (sbuf));
646  }
647 
648  ZE_MessageNotice(8, "%s", sbuf);
649  }
650  }
651 
652 fin:
653  return;
654 }
655 
656 /* ****************************************************************************
657  * *
658  * *
659  ******************************************************************************/
660 #define UNDEF_TAG "[SUSPECT]"
661 
662 bool
664  SMFICTX *ctx;
665  char *tag;
666 {
667  CTXPRIV_T *priv = MLFIPRIV(ctx);
668  char *osubject = NULL;
669  bool result = TRUE;
670  char *ntag = UNDEF_TAG;
671 
672  if (tag != NULL && strlen(tag) > 0)
673  ntag = tag;
674 
675  osubject = STRNULL(priv->hdr_subject, "");
676 #if 0
677  if (!zeStrRegex(osubject, ntag, NULL, NULL, TRUE))
678 #else
679  if (strstr(osubject, ntag) == NULL)
680 #endif
681  {
682  char *nsubject = NULL;
683  size_t sz;
684 
685  sz = strlen(osubject) + strlen(ntag) + 8;
686  if ((nsubject = (char *) malloc(sz)) != NULL) {
687  snprintf(nsubject, sz, "%s %s", ntag, osubject);
688  result = (smfi_chgheader(ctx, "Subject", 1, nsubject) == MI_SUCCESS);
689  FREE(nsubject);
690  } else {
691  ZE_LogSysError("malloc error");
692  result = FALSE;
693  }
694  }
695 
696  return result;
697 }
698 
699 /* ****************************************************************************
700  * *
701  * *
702  ******************************************************************************/
703 static pthread_mutex_t scf_mutex = PTHREAD_MUTEX_INITIALIZER;
704 static int scf_fd = -1;
705 static int scf_nerr = 0;
706 
707 #define ZE_SERIES_FNAME ZE_WORKDIR "/ze-series.txt"
708 
709 bool
711 {
712  bool ret = TRUE;
713  char *fname = ZE_SERIES_FNAME;
714 
715  if (scf_fd < 0) {
716  scf_fd = open(fname, O_WRONLY | O_CREAT | O_APPEND, 0644);
717  if (scf_fd < 0) {
718  ZE_LogSysError("Error opening %s", fname);
719  scf_nerr++;
720  ret = FALSE;
721  } else
722  scf_nerr = 0;
723  }
724  return ret;
725 }
726 
727 bool
729 {
730  bool ret = TRUE;
731  char *fname = ZE_SERIES_FNAME;
732 
733  MUTEX_LOCK(&scf_mutex);
734  if (scf_fd >= 0) {
735  close(scf_fd);
736  scf_fd = -1;
737  }
738 
739  scf_fd = open(fname, O_WRONLY | O_CREAT | O_APPEND, 0644);
740  if (scf_fd < 0) {
741  ZE_LogSysError("Error opening %s", fname);
742  scf_nerr++;
743  ret = FALSE;
744  } else
745  scf_nerr = 0;
746 
747  MUTEX_UNLOCK(&scf_mutex);
748 
749  return TRUE;
750 }
751 
752 
753 /* ****************************************************************************
754  * *
755  * *
756  ******************************************************************************/
757 #define GLOBAL_CLASS(s) ((s) >= 4 ? "FORT": ((s) > 1 ? "FAIBLE" : "HAM"))
758 
759 #define BAYES_CLASS(s) ((s) >= BSCORE_HI ? "SPAM": ((s) > BSCORE_LO ? "UNSURE" : "HAM"))
760 
761 #define SPAM_CLASS(s) ((s) >= BSCORE_HI ? "SPAM" : (((s) >= BSCORE_MI ? "LO" : ((s) > 0.25 ? "UNSURE" : "HAM"))))
762 
763 bool
765  SMFICTX *ctx;
766 {
767  CTXPRIV_T *priv = MLFIPRIV(ctx);
768 
769  char *fname = ZE_SERIES_FNAME;
770  int gScore;
771  char buf[1024];
772  char from[256];
773 
774 #if 0
775  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
776  static int scf_fd = -1;
777  static int scf_nerr = 0;
778 #endif
779 
780  ASSERT(priv != NULL);
781 
782  MUTEX_LOCK(&scf_mutex);
783  if (scf_fd < 0) {
784  scf_fd = open(fname, O_WRONLY | O_CREAT | O_APPEND, 0644);
785  if (scf_fd < 0) {
786  ZE_LogSysError("Error opening %s", fname);
787  scf_nerr++;
788  }
789  }
790 
791  if (scf_fd >= 0) {
792  msg_scores_T *scp;
793 
794  scp = &priv->rawScores;
795 
796 #if 0
797  gScore = combine_scores(&priv->netScores);
798 #endif
799  memset(from, 0, sizeof (from));
800  extract_email_address(from, priv->env_from, sizeof (from));
801 
802 #if 1
803  gScore = scp->scale.kf1 * (scp->combined - scp->scale.kf0);
804 
805 #if 1
806  snprintf(buf, sizeof (buf),
807  "%10ld SCORE=%.3f GSCORE=%d CLASS=%s B=%.3f R=%d O=%d U=%d IP=%s FROM=%s\n",
808  time(NULL),
809  scp->combined,
810  gScore, SPAM_CLASS(scp->combined),
811  scp->bayes,
812  scp->body + scp->headers,
813  scp->oracle, scp->urlbl, priv->peer_addr, priv->env_from);
814 #else
815  snprintf(buf, sizeof (buf),
816  "%10ld SCORE=%5d %-6s %6.3f %-6s %5d %5d %5d %-16s %s\n",
817  time(NULL),
818  gScore, GLOBAL_CLASS(gScore), scp->bayes,
819  BAYES_CLASS(scp->bayes),
820  scp->body + scp->headers,
821  scp->oracle, scp->urlbl, priv->peer_addr, priv->env_from);
822 #endif
823 #else
824  snprintf(buf, sizeof (buf),
825  "%10ld %5d %-6s %6.3f %-6s %5d %5d %5d %-16s %s\n", time(NULL),
826  gScore, GLOBAL_CLASS(gScore), priv->rawScores.bayes,
827  BAYES_CLASS(priv->rawScores.bayes),
828  priv->rawScores.body + priv->rawScores.headers,
829  priv->rawScores.oracle, priv->rawScores.urlbl, priv->peer_addr,
830  priv->env_from);
831 #endif
832 
833  if (write(scf_fd, buf, strlen(buf)) < strlen(buf)) {
834  ZE_LogSysError("Error writing into file %s", fname);
835  close(scf_fd);
836  scf_fd = -1;
837  scf_nerr++;
838  } else
839  scf_nerr = 0;
840  }
841  MUTEX_UNLOCK(&scf_mutex);
842 
843  return TRUE;
844 }
#define OPT_SHOW
Definition: ze-cf.h:55
double combined
Definition: ze-msg-score.h:73
rcpt_addr_T * env_rcpt
#define STRBOOL(x, t, f)
Definition: macros.h:87
msg_scores_T rawScores
char * rcpt
Definition: ze-rcpt-list.h:31
#define SMFIS_ACCEPT
char * fname
int Smfi_ChgFrom(SMFICTX *ctx, char *mail, char *args)
Definition: ze-libmilter.c:172
#define ASSERT(a)
Definition: macros.h:27
#define SMFIS_TEMPFAIL
#define NULLSENDER
Definition: macros.h:229
#define GLOBAL_CLASS(s)
#define CRLF
Definition: macros.h:224
#define FREE(x)
Definition: macros.h:37
bool add_tag2subject(SMFICTX *ctx, char *tag)
#define MUTEX_UNLOCK(mutex)
Definition: macros.h:101
char * peer_addr
#define CALLBACK_EHLO
Definition: ze-callback.h:29
#define STRNULL(x, r)
Definition: macros.h:81
bool reopen_scores4stats_file()
char * reply_code
void zeStrCenter(char *, char *, int)
Definition: zeStrings.c:586
#define CALLBACK_RCPT
Definition: ze-callback.h:31
sfsistat do_notify(SMFICTX *ctx, attachment_T *ahead, char *answer, char *why, char *tag)
#define MUTEX_LOCK(mutex)
Definition: macros.h:93
pthread_mutex_t mutex
Definition: ze-connopen.c:63
char * hdr_mailer
#define FALSE
Definition: macros.h:160
#define SMFIS_CONTINUE
#define SMFIS_REJECT
#define strlcpy
Definition: zeString.h:32
#define ZE_LogMsgError(level,...)
Definition: zeSyslog.h:113
#define ADJUST_FILENAME(path, fname, cfdir, defval)
Definition: macros.h:236
#define UNDEF_TAG
#define CF_ZE_SUBJECT
Definition: cfh-defs.h:91
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
char * extract_email_address(char *, char *, size_t)
#define OPT_YES
Definition: ze-cf.h:45
bool dump_msg_scores4stats(SMFICTX *ctx)
#define CF_NOTIFY_SENDER
Definition: cfh-defs.h:88
char * env_to
int cf_get_int(int id)
Definition: ze-cf.c:803
#define MLFIPRIV(ctx)
#define SPAM_CLASS(s)
char * callback_name(int id)
Definition: ze-smmacros.c:267
#define strlcat
Definition: zeString.h:28
#define strchr
Definition: ze-sys.h:218
char my_hostname[]
Definition: ze-filter.c:89
CONNID_T id
#define CF_CONFDIR
Definition: cfh-defs.h:51
unsigned long msg_size
scores_scale_T scale
Definition: ze-msg-score.h:93
#define ZE_MessageNotice(level,...)
Definition: zeSyslog.h:91
#define OPT_SENDER
Definition: ze-cf.h:63
char * hdr_to
#define RCPT_OK
Definition: ze-rcpt.h:38
char * zeMyBasename(char *, char *, size_t)
Definition: zeFileTools.c:31
#define WARN_MSG_SIZE
#define CF_NOTIFY_RCPT
Definition: cfh-defs.h:89
rcpt_addr_T * next
Definition: ze-rcpt-list.h:39
char * zeStrSet(char *, int, int)
Definition: zeStrings.c:330
#define JCOMBUFSZ
Definition: ze-filter.h:184
char * fsuffix
#define CALLBACK_MAIL
Definition: ze-callback.h:30
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
int nb
Definition: ze-connopen.c:61
#define SMFIS_DISCARD
#define TRUE
Definition: macros.h:157
#define ZE_SERIES_FNAME
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
char * cf_get_str(int id)
Definition: ze-cf.c:854
double bayes
Definition: ze-msg-score.h:88
char * mimetype
Definition: ze-mimelist.h:72
char * peer_name
#define CTX_NETCLASS_LABEL(priv)
msg_scores_T netScores
char * env_from
#define CF_ZE_SENDER
Definition: cfh-defs.h:90
char * helohost
sm_mac_T * sm
#define CF_FOOTER
Definition: cfh-defs.h:33
#define CONNID_STR(connid)
Definition: ze-filter.h:113
bool check_address_ok2warn(char *p)
char * hdr_subject
char * hdr_from
#define ZE_CONFDIR
Definition: defs.h:36
#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
#define ZE_ERROR_MSG_FILE
Definition: defs.h:50
void log_msg_context(SMFICTX *ctx, char *why)
#define CF_ERROR_MSG_FILE
Definition: cfh-defs.h:52
#define SUFFIX_UNKNOWN
Definition: ze-spool.h:36
struct attachment_T * next
Definition: ze-mimelist.h:74
void read_error_msg(char *buf, int sz, attachment_T *ahead, char *answer, char *from, char *why, char *tag, CTXPRIV_T *priv)
int msg[MAX_SCORE+2]
Definition: ze-stats.c:41
char * sm_msgid
bool open_scores4stats_file()
#define OPT_SUBJECT
Definition: ze-cf.h:65
#define BAYES_CLASS(s)