ze-filter  (ze-filter-0.8.0-develop-180218)
ze-reply.c
Go to the documentation of this file.
1 
2 /*
3  *
4  * ze-filter - Mail Server Filter for sendmail
5  *
6  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
7  *
8  * Auteur : Jose Marcio Martins da Cruz
9  * jose.marcio.mc@gmail.org
10  *
11  * Historique :
12  * Creation : janvier 2002
13  *
14  * This program is free software, but with restricted license :
15  *
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * More details about ze-filter license can be found at ze-filter
22  * web site : http://foss.jose-marcio.org
23  */
24 
25 #include <ze-sys.h>
26 
27 #include "ze-filter.h"
28 #include "ze-filter-data.h"
29 
30 /* ****************************************************************************
31  * *
32  * *
33  ******************************************************************************/
34 
35 
36 static bool rule2reply(SMFICTX *, char *, char *, size_t, char *,
37  char *);
38 
39 typedef struct replymsg_T {
40  char *code;
41  char *msg;
42 } replymsg_T;
43 
44 static replymsg_T replymsg[] = {
45  {"NO_PEER_HOSTNAME", "*** No peer hostname when connecting"},
46  {"XFILE",
47  "*** A suspicious file (executable code) was found in the message!"},
48  {"NO_FROM_HEADER", "*** There is no From: header field"},
49  {"NO_RCPT_HEADER", "*** There is no To, CC or Bcc header field"},
50  {"NO_SUBJECT_HEADER", "*** There is no Subject Header"},
51  {"NO_HEADERS", "*** There are no headers..."},
52  {"INTRANET_USER", "*** Mail to intranet user from outside world..."},
53  {"LOCAL_USER", "*** %s can receive mail only from local network"},
54  {"BINARY_MESSAGE", "*** Trying a buffer overflow ??? - Let's discard it! "},
55  {"VIRUS", "*** A virus was detected in your message"},
56  {"POLICY", "*** This message violates our policy"},
57  {"TOO_MUCH_RCPT", "*** Too many recipients for this message"},
58  {"RESOLVE_FAIL", "*** RESOLVE : mail gateway DNS lookup failed"},
59  {"RESOLVE_FORGED", "*** RESOLVE : mail gateway hostname seems to be forged"},
60  {"TOO_MUCH_EMPTY_CONN", "*** Too many empty connections"},
61  {"TOO_MUCH_BADRCPT", "*** Harvesting ???"},
62  {"TOO_MUCH_OPEN_CONN", "*** Too many open connections"},
63  {"THROTTLE_EXCEEDED", "*** CONN THROTTLE : too high"},
64  {"RCPT_THROTTLE_EXCEEDED", "*** RCPT THROTTLE : too high"},
65  {"FROM_CONTENTS", "*** From: contents violates our site policy"},
66  {"SUBJECT_CONTENTS", "*** Subject: contents violates our site policy"},
67  {"HEADERS_CONTENTS", "*** Header contents violates our site policy"},
68  {"BODY_CONTENTS",
69  "*** Sorry, this server is configured to refuse that is indistinguishable from spam"},
70  {"HELO_CONTENTS", "*** HELO contents : strange!!!"},
71  {"TEXT_NOT_ALLOWED", "*** Message contents violate our site policy"},
72  {"ENCODED_BODY", "*** We don't accept encoded messages"},
73  {"BODY_ENCODED_BINARY", "*** No BINARY messages!"},
74  {"BODY_ENCODED_BASE64", "*** No BASE 64 messages!"},
75  {"BODY_ENCODED_QP", "*** No QUOTED PRINTABLE messages!"},
76  {"BAD_NULL_SENDER", "*** Bad NULL sender"},
77  {NULL, NULL}
78 };
79 
80 static char *
81 reply_code2msg(code)
82  char *code;
83 {
84  replymsg_T *p = replymsg;
85 
86  if (p == NULL)
87  return NULL;
88 
89  while (p->code != NULL) {
90  if (strcasecmp(p->code, code) == 0)
91  return p->msg;
92  p++;
93  }
94 
95  return NULL;
96 }
97 
98 /* ****************************************************************************
99  * *
100  * *
101  ******************************************************************************/
102 #define STRING(a) #a
103 
104 bool
105 get_reply_msg(ctx, code, msg, sz, attr, value)
106  SMFICTX *ctx;
107  char *code;
108  char *msg;
109  size_t sz;
110  char *attr;
111  char *value;
112 {
113 #if 0
114  CTXPRIV_T *priv = MLFIPRIV(ctx);
115 #endif
116  char b_in[256];
117 
118  char b_out[1024];
119  char *sin = NULL, *sout = NULL;
120  bool result = FALSE;
121 
122  if (db_policy_check("ReplyMsg", code, b_in, sizeof (b_in)))
123  sin = b_in;
124  else
125  sin = reply_code2msg(code);
126 
127  if (sin == NULL)
128  ZE_LogMsgWarning(0, "Can't get message for code : %s", code);
129 
130  if ((sin != NULL)
131  && rule2reply(ctx, b_out, b_in, sizeof (b_out), attr, value)) {
132  zeSafeStrnCpy(msg, sz, b_out, strlen(b_out));
133  result = TRUE;
134  } else {
135  sout = "*** Unknown error";
136 
137  zeSafeStrnCpy(msg, sz, sout, strlen(sout));
138  result = TRUE;
139  }
140 
141  return result;
142 }
143 
144 
145 /* ****************************************************************************
146  * *
147  * *
148  ******************************************************************************/
149 static bool
150 rule2reply(ctx, out, in, sz, attr, value)
151  SMFICTX *ctx;
152  char *out;
153  char *in;
154  size_t sz;
155  char *attr;
156  char *value;
157 {
158  CTXPRIV_T *priv = MLFIPRIV(ctx);
159  char *p, *q;
160  long pi, pf;
161 
162  if (in == NULL || out == NULL)
163  return FALSE;
164 
165  if (sz-- < 1)
166  return FALSE;
167 
168  p = in;
169  q = out;
170  while ((sz > 0) && zeStrRegex(p, "__[A-Z0-9_]+__", &pi, &pf, TRUE)) {
171  char *tag = NULL;
172  int n;
173 
174  if (pi > 0) {
175  n = zeSafeStrnCat(q, sz, p, pi);
176  p += pi;
177  q += n;
178  sz -= n;
179 
180  continue;
181  }
182 
183  /*
184  ** Check for variables...
185  */
186  if ((attr != NULL) && (strlen(attr) > 0)
187  && (strncasecmp(p, attr, strlen(attr)) == 0)) {
188  if (value != NULL) {
189  n = zeSafeStrnCat(q, sz, value, strlen(value));
190  q += n;
191  sz -= n;
192  }
193  p += pf;
194  continue;
195  }
196 
197  tag = "__VIRUS__";
198  if (strncasecmp(p, tag, strlen(tag)) == 0) {
199 
200  p += pf;
201  continue;
202  }
203 
204  tag = "__VIRUS__";
205  if (strncasecmp(p, tag, strlen(tag)) == 0) {
206 
207  p += pf;
208  continue;
209  }
210 
211  tag = "__CLNT_ADDR__";
212  if (strncasecmp(p, tag, strlen(tag)) == 0) {
213  char *addr = NULL;
214 
215  addr = (priv != NULL && priv->peer_addr) ? priv->peer_addr : "???";
216 
217  n = zeSafeStrnCat(q, sz, addr, strlen(addr));
218 
219  /*
220  * printf(" pi = %ld; pf = %ld; n = %d\n", pi, pf, n);
221  */
222 
223  q += n;
224  sz -= n;
225 
226  p += pf;
227  continue;
228  }
229 
230  tag = "__CLNT_NAME__";
231  if (strncasecmp(p, tag, strlen(tag)) == 0) {
232 
233  p += pf;
234  continue;
235  }
236 
237  tag = "__FROM__";
238  if (strncasecmp(p, tag, strlen(tag)) == 0) {
239 
240  p += pf;
241  continue;
242  }
243 
244  tag = "__TO__";
245  if (strncasecmp(p, tag, strlen(tag)) == 0) {
246 
247  p += pf;
248  continue;
249  }
250 
251  p += pf;
252  }
253 
254  if (p != NULL)
255  (void) zeSafeStrnCat(q, sz, p, strlen(p));
256 
257  return TRUE;
258 }
bool get_reply_msg(SMFICTX *ctx, char *code, char *msg, size_t sz, char *attr, char *value)
Definition: ze-reply.c:105
char * code
Definition: ze-reply.c:40
char * msg
Definition: ze-reply.c:41
char * peer_addr
#define FALSE
Definition: macros.h:160
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
#define MLFIPRIV(ctx)
bool db_policy_check(char *prefix, char *key, char *bufout, size_t szbuf)
Definition: ze-dbpolicy.c:141
int zeSafeStrnCpy(char *, size_t, char *, size_t)
Definition: zeStrings.c:136
#define TRUE
Definition: macros.h:157
int zeSafeStrnCat(char *, size_t, char *, size_t)
Definition: zeStrings.c:107
#define ZE_LogMsgWarning(level,...)
Definition: zeSyslog.h:112
struct replymsg_T replymsg_T