ze-filter  (ze-filter-0.8.0-develop-180218)
ze-smtp-divers.c
Go to the documentation of this file.
1 /*
2  *
3  * ze-filter - Mail Server Filter for sendmail
4  *
5  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
6  *
7  * Auteur : Jose Marcio Martins da Cruz
8  * jose.marcio.mc@gmail.org
9  *
10  * Historique :
11  * Creation : janvier 2002
12  *
13  * This program is free software, but with restricted license :
14  *
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * More details about ze-filter license can be found at ze-filter
21  * web site : http://foss.jose-marcio.org
22  */
23 
24 #include <ze-sys.h>
25 #include <libze.h>
26 #include "ze-libjc.h"
27 
28 /* ****************************************************************************
29  * *
30  * *
31  **************************************************************************** */
32 #define DATE_RE_1 "[0-9]+ " \
33  "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)+ " \
34  "[0-9]+ [0-9]+:[0-9]+:[0-9]+"
35 
36 #define DATE_RE_2 "[0-9]+ " \
37  "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)+ " \
38  "[0-9]+ [0-9]+:[0-9]+"
39 
40 time_t
42  char *date;
43 {
44  time_t secs = 0;
45  long pi = 0;
46  char *p;
47  struct tm tm;
48 
49  char *strptime(const char *s, const char *format, struct tm *tm);
50 
51  if (date == NULL)
52  goto fin;
53 
54  if (zeStrRegex(date, DATE_RE_1, &pi, NULL, TRUE))
55  {
56  char buf[256];
57  long hour = 0;
58  char *format = NULL;
59  size_t sz;
60 
61  memset(buf, 0, sizeof (buf));
62  sz = strlen(date) - pi;
63  sz = MIN(sizeof (buf) - 1, sz);
64 
65  strncpy(buf, date + pi, sz);
66 
67  format = "%d %b %Y %H:%M:%S";
68  if ((p = strptime(buf, format, &tm)) != NULL)
69  hour = zeStr2long(p, NULL, 0) / 100;
70 
71  if (tm.tm_year >= 138) {
72  ZE_MessageNotice(10, "Date invalid ??? %s", date);
73  tm.tm_year = MIN(135, tm.tm_year);
74  }
75 
76  secs = mktime(&tm) + hour * 3600;
77 
78  ZE_MessageInfo(15, "%d %d %d %02d %02d %02d %ld\n",
79  tm.tm_mday, tm.tm_mon,
80  tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec, secs);
81 
82  goto fin;
83  }
84 
85  if (zeStrRegex(date, DATE_RE_2, &pi, NULL, TRUE))
86  {
87  char buf[256];
88  long hour = 0;
89  char *format = NULL;
90  size_t sz;
91 
92  memset(buf, 0, sizeof (buf));
93  sz = strlen(date) - pi;
94  sz = MIN(sizeof (buf) - 1, sz);
95 
96  strncpy(buf, date + pi, sz);
97 
98  format = "%d %b %Y %H:%M";
99  if ((p = strptime(buf, format, &tm)) != NULL)
100  hour = zeStr2long(p, NULL, 0) / 100;
101 
102  if (tm.tm_year >= 138) {
103  ZE_MessageNotice(10, "Date invalid ??? %s", date);
104  tm.tm_year = MIN(135, tm.tm_year);
105  }
106 
107  secs = mktime(&tm) + hour * 3600;
108 
109  ZE_MessageInfo(15, "%d %d %d %02d %02d %02d %ld\n",
110  tm.tm_mday, tm.tm_mon,
111  tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec, secs);
112 
113  goto fin;
114  }
115 
116 fin:
117  ZE_MessageInfo(13, "header_date2secs : %s -> %ld", STRNULL(date, "NULL"), secs);
118 
119  return secs;
120 }
121 
122 
123 /* ***************************************************************************
124  * *
125  * *
126  *****************************************************************************/
127 char *
129  char *dst;
130  char *org;
131  size_t sz;
132 {
133  char *expr = "<.*@.*>";
134  long pi, pf;
135 
136  expr = "<.*>";
137 
138  if (dst != NULL && sz > 0)
139  memset(dst, 0, sz);
140 
141  if ((dst == NULL) || (org == NULL) || (sz == 0))
142  return dst;
143 
144  pi = pf = 0;
145 
146  if (zeStrRegex(org, expr, &pi, &pf, TRUE))
147  {
148  if (pf - pi - 1 <= sz)
149  sz = pf - pi - 1;
150 
151  strlcpy(dst, org + pi + 1, sz);
152 
153  ZE_MessageInfo(19, "OK %s %s", org, dst);
154  } else
155  {
156  int l = strlen(org);
157 
158  memset(dst, 0, sz);
159  if (l >= sz)
160  l = sz - 1;
161  strncpy(dst, org, l);
162 
163  ZE_MessageInfo(19, "KO %s %s", org, dst);
164  }
165  zeStr2Lower(dst);
166 
167  return dst;
168 }
169 
170 /* ***************************************************************************
171  * *
172  * *
173  *****************************************************************************/
174 char *
176  char *dst;
177  char *org;
178  size_t sz;
179 {
180  char *expr = "<.*>";
181 
182  long pi, pf;
183 
184  ASSERT(dst != NULL);
185 
186  if (dst == NULL || sz == 0)
187  return dst;
188 
189  if (org == NULL)
190  return NULL;
191 
192  *dst = '\0';
193 
194  pi = pf = 0;
195 
196  if (zeStrRegex(org, expr, &pi, &pf, TRUE))
197  {
198  int n;
199 
200  n = strcspn(org + pi, "@");
201  pi += n;
202 
203  if (pf - pi - 1 <= sz)
204  sz = pf - pi - 1;
205 
206  strlcpy(dst, org + pi + 1, sz);
207  zeStr2Lower(dst);
208  } else
209  {
210  char *p = strchr(org, '@');
211 
212  if (p != NULL)
213  {
214  p++;
215  strlcpy(dst, p, sz);
216  }
217  }
218 
219  return dst;
220 }
221 
222 
223 /* ***************************************************************************
224  * *
225  * *
226  *****************************************************************************/
227 #ifndef SMFIS_CONTINUE
228 # define SMFIS_CONTINUE 0
229 # define SMFIS_REJECT 1
230 # define SMFIS_DISCARD 2
231 # define SMFIS_ACCEPT 3
232 # define SMFIS_TEMPFAIL 4
233 #endif /* SMFIS_CONTINUE */
234 
235 int
237  smtp_reply_T *r;
238  char *s;
239 {
240  if (s == NULL || r == NULL)
241  return SMFIS_CONTINUE;
242 
243  memset(r, 0, sizeof (*r));
244  r->result = SMFIS_CONTINUE;
245  r->signature = SIGNATURE;
246 
247  if (zeStrRegex(s, "^ERROR", NULL, NULL, TRUE))
248  {
249  if (zeStrRegex(s, "^ERROR:[0-9]{3}:[0-9]\\.[0-9]\\.[0-9]:", NULL, NULL, TRUE))
250  {
251  char *p = s;
252  int n;
253 
254  p += strcspn(p, ":") + 1;
255  n = strcspn(p, ":");
256  if (n >= sizeof (r->rcode))
257  n = sizeof (r->rcode) - 1;
258  strncpy(r->rcode, p, n);
259 
260  p += strcspn(p, ":") + 1;
261  n = strcspn(p, ":");
262  if (n >= sizeof (r->xcode))
263  n = sizeof (r->xcode) - 1;
264  strncpy(r->xcode, p, n);
265 
266  p += strcspn(p, ":") + 1;
267  strlcpy(r->msg, p, sizeof (r->msg));
268 
269  switch (*(r->rcode))
270  {
271  case '4':
272  r->result = SMFIS_TEMPFAIL;
273  break;
274  case '5':
275  r->result = SMFIS_REJECT;
276  break;
277  default:
278  r->result = SMFIS_REJECT;
279  break;
280  }
281  } else
282  {
283  snprintf(r->rcode, sizeof (r->rcode), "550");
284  snprintf(r->xcode, sizeof (r->xcode), "5.7.0");
285  snprintf(r->msg, sizeof (r->msg), "Access denied");
286 
287  r->result = SMFIS_REJECT;
288  }
289  goto fin;
290  }
291 
292  if (zeStrRegex(s, "^OK", NULL, NULL, TRUE))
293  {
294  r->result = SMFIS_CONTINUE;
295  goto fin;
296  }
297 
298  if (zeStrRegex(s, "^REJECT", NULL, NULL, TRUE))
299  {
300  snprintf(r->rcode, sizeof (r->rcode), "550");
301  snprintf(r->xcode, sizeof (r->xcode), "5.7.0");
302  snprintf(r->msg, sizeof (r->msg), "Access denied");
303 
304  r->result = SMFIS_REJECT;
305  goto fin;
306  }
307 
308  if (zeStrRegex(s, "^TEMPFAIL", NULL, NULL, TRUE))
309  {
310  snprintf(r->rcode, sizeof (r->rcode), "421");
311  snprintf(r->xcode, sizeof (r->xcode), "4.5.1");
312  snprintf(r->msg, sizeof (r->msg),
313  "For some reason I can't serve you now. Try again later.");
314 
315  r->result = SMFIS_TEMPFAIL;
316  goto fin;
317  }
318 
319  if (zeStrRegex(s, "^[0-9]{3}:[0-9]\\.[0-9]\\.[0-9]:.+", NULL, NULL, TRUE))
320  {
321  char *argv[4];
322  int argc;
323 
324  memset(argv, 0, sizeof (argv));
325  argc = zeStr2Tokens(s, 4, argv, ":");
326 
327  if (argc >= 2)
328  {
329  if (argv[0] == NULL || strlen(argv[0]) == 0)
330  goto fin;
331  if (argv[1] == NULL || strlen(argv[1]) == 0)
332  goto fin;
333  if (argv[2] == NULL || strlen(argv[2]) == 0)
334  argv[2] = "Unknown reason...";
335 
336  strlcpy(r->rcode, argv[0], sizeof (r->rcode));
337  strlcpy(r->xcode, argv[1], sizeof (r->xcode));
338  strlcpy(r->msg, argv[2], sizeof (r->msg));
339 
340  switch (*(r->rcode))
341  {
342  case '4':
343  r->result = SMFIS_TEMPFAIL;
344  break;
345  case '5':
346  r->result = SMFIS_REJECT;
347  break;
348  default:
349  r->result = SMFIS_REJECT;
350  break;
351  }
352  }
353  }
354 
355 fin:
356 
357  return r->result;
358 }
359 
360 /* ***************************************************************************
361  * *
362  * *
363  *****************************************************************************/
364 bool
365 jc_fill_reply(r, rcode, xcode, msg, result)
366  smtp_reply_T *r;
367  char *rcode;
368  char *xcode;
369  char *msg;
370  int result;
371 {
372  ASSERT(r != NULL);
373  ASSERT(rcode != NULL);
374  ASSERT(xcode != NULL);
375  ASSERT(msg != NULL);
376 
377  jc_reply_free(r);
378 
379  /* XXX A voir */
380  if (*xcode != *rcode)
381  {
382  ZE_LogMsgError(0, "rcode=(%s) and xcode=(%s) don't match", rcode, xcode);
383  return FALSE;
384  }
385  if (strlen(rcode) == 0)
386  return FALSE;
387  if (strlen(xcode) == 0)
388  return FALSE;
389 
390  if (strlen(msg) == 0)
391  msg = "Unknown why... ";
392 
393  strlcpy(r->rcode, rcode, sizeof (r->rcode));
394  strlcpy(r->xcode, xcode, sizeof (r->xcode));
395  strlcpy(r->msg, msg, sizeof (r->msg));
396  r->result = result;
397 
398  return TRUE;
399 }
400 
401 /* ***************************************************************************
402  * *
403  * *
404  *****************************************************************************/
405 void
407  smtp_reply_T *r;
408 {
409  if (r == NULL)
410  return;
411 
412  memset(r, 0, sizeof (*r));
413 }
uint32_t signature
#define ASSERT(a)
Definition: macros.h:27
#define SMFIS_TEMPFAIL
#define STRNULL(x, r)
Definition: macros.h:81
#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
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
char * extract_email_address(char *dst, char *org, size_t sz)
int zeStr2Tokens(char *, int, char **, char *)
Definition: zeStrings.c:610
#define MIN(a, b)
Definition: macros.h:140
#define strchr
Definition: ze-sys.h:218
long zeStr2long(char *s, int *error, long dval)
Definition: zeStrConvert.c:35
#define ZE_MessageNotice(level,...)
Definition: zeSyslog.h:91
bool jc_fill_reply(smtp_reply_T *r, char *rcode, char *xcode, char *msg, int result)
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
time_t header_date2secs(char *date)
void jc_reply_free(smtp_reply_T *r)
#define DATE_RE_2
#define TRUE
Definition: macros.h:157
char * extract_host_from_email_address(char *dst, char *org, size_t sz)
int jc_string2reply(smtp_reply_T *r, char *s)
char msg[256]
char * zeStr2Lower(char *)
Definition: zeStrings.c:295
#define DATE_RE_1
#define SIGNATURE
Definition: ze-libjc.h:75
int msg[MAX_SCORE+2]
Definition: ze-stats.c:41