ze-filter  (ze-filter-0.8.0-develop-180218)
ze-dbpolicy.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 
29 /* ****************************************************************************
30  * *
31  * *
32  **************************************************************************** */
33 #define DREF 32
34 
35 
36 static ZEDB_T hdb = ZEDB_INITIALIZER;
37 static bool rdonly = TRUE;
38 
39 /* ****************************************************************************
40  * *
41  * *
42  **************************************************************************** */
43 bool
45  bool rd;
46 {
47  bool res = TRUE;
48 
49  char *dbname;
50  char dbpath[1024];
51  char *cfdir = NULL;
52 
53  memset(dbpath, 0, sizeof (dbpath));
54 
55  cfdir = cf_get_str(CF_CDBDIR);
56  if (cfdir == NULL || strlen(cfdir) == 0)
57  cfdir = ZE_CDBDIR;
58 
59  dbname = cf_get_str(CF_DB_POLICY);
60  ADJUST_FILENAME(dbpath, dbname, cfdir, "ze-policy.db");
61 
62  ZE_MessageInfo(15, "Opening Policy Database : %s", dbpath);
63 
64  if (zeDb_OK(&hdb))
65  return TRUE;
66 
67  zeDb_Lock(&hdb);
68  rdonly = rd;
69  if (!zeDb_OK(&hdb))
70  res =
71  zeDb_Open(&hdb, NULL, dbpath, (rdonly ? 0444 : 0644), rdonly, TRUE, 0);
72  zeDb_Unlock(&hdb);
73 
74  return res;
75 }
76 
77 /* ****************************************************************************
78  * *
79  * *
80  **************************************************************************** */
81 bool
83 {
84  bool res = TRUE;
85  char path[1024];
86 
87  zeDb_Lock(&hdb);
88 
89  if (zeDb_OK(&hdb))
90  res = zeDb_Close(&hdb);
91 
92  snprintf(path, sizeof (path), "%s/%s", cf_get_str(CF_CDBDIR), "ze-policy.db");
93 
94  res = zeDb_Open(&hdb, NULL, path, (rdonly ? 0444 : 0644), rdonly, TRUE, 0);
95  zeDb_Unlock(&hdb);
96 
97  return res;
98 }
99 
100 /* ****************************************************************************
101  * *
102  * *
103  **************************************************************************** */
104 bool
106 {
107  bool res = TRUE;
108 
109  if (!zeDb_OK(&hdb))
110  return res;
111 
112  zeDb_Lock(&hdb);
113  if (zeDb_OK(&hdb))
114  res = zeDb_Close(&hdb);
115  zeDb_Unlock(&hdb);
116 
117  return res;
118 }
119 
120 /* ****************************************************************************
121  * *
122  * *
123  **************************************************************************** */
124 #define MAX_ERR 8
125 
126 /*
127 ** Checks order
128 **
129 ** 1. Full check of key
130 ** 2. If key is an IP address,
131 ** Check IP and IP nets
132 ** 3. If key is a domain name
133 ** Check domain and sous domains
134 ** 4. If key is an email address
135 ** check user part
136 **
137 */
138 #define DBG_LEVEL 15
139 
140 bool
141 db_policy_check(prefix, key, bufout, size)
142  char *prefix;
143  char *key;
144  char *bufout;
145  size_t size;
146 {
147  char k[256];
148  char v[1024];
149  bool found = FALSE;
150  char *p = NULL;
151  char *domain = NULL;
152  static int nerr = 0;
153  bool is_email = FALSE;
154  char *email = NULL;
155 
156  if (!zeDb_OK(&hdb) && !db_policy_open(TRUE)) {
157  if (nerr++ < MAX_ERR)
158  ZE_LogMsgError(0, "Can't open policy database");
159  return FALSE;
160  }
161 
162  if (key == NULL)
163  return FALSE;
164 
165  if (strlen(key) == 0)
166  key = "default";
167 
168  nerr = 0;
169  zeDb_Lock(&hdb);
170 
171  /*
172  * let's get the domain part and check if this is an email
173  * ** address
174  */
175  if ((domain = strchr(key, '@')) != NULL) {
176  is_email = TRUE;
177 
178  if ((email = strdup(key)) != NULL)
179  (void) extract_email_address(email, key, strlen(key) + 1);
180  else
181  ZE_LogSysError("strdup(%s) error", key);
182 
183  domain++;
184  } else
185  domain = key;
186 
187  /*
188  * if this is an email address, let's first check
189  * ** the entire key
190  */
191  if (is_email) {
192  /*
193  * First of all, let's check the entire key
194  */
195  snprintf(k, sizeof (k), "%s:%s", prefix, email);
196  (void) zeStr2Lower(k);
197  ZE_MessageInfo(DBG_LEVEL, "KEY FULL : Looking for %s ...", k);
198  if (zeDb_GetRec(&hdb, k, v, sizeof (v))) {
199  if ((bufout != NULL) && (size > 0))
200  strlcpy(bufout, v, size);
201  ZE_MessageInfo(DBG_LEVEL, " : Found %s %s...", k, v);
202  found = TRUE;
203  goto fin;
204  }
205 
206  if (!found) {
207 
208  }
209  }
210 
211  if (found)
212  goto fin;
213 
214  ZE_MessageInfo(DBG_LEVEL, "db_policy : domain = %s", domain);
215 
216  /*
217  * Entire key doesn't match - lets check domain part
218  */
219  if (zeStrRegex(domain, IPV4_ADDR_REGEX, NULL, NULL, TRUE)) {
220  /*
221  * This is a numeric IP address
222  */
223 
224  snprintf(k, sizeof (k), "%s:%s", prefix, domain);
225  (void) zeStr2Lower(k);
226  p = k;
227  /*
228  * Try each part beginning from the most complete one
229  */
230  while (strlen(k) > 0) {
231  ZE_MessageInfo(DBG_LEVEL, "IP : Looking for %s ...", k);
232  if (zeDb_GetRec(&hdb, k, v, sizeof (v))) {
233  if ((bufout != NULL) && (size > 0))
234  strlcpy(bufout, v, size);
235  ZE_MessageInfo(DBG_LEVEL, " : Found %s %s...", k, v);
236  found = TRUE;
237  break;
238  }
239  if ((p = strrchr(k, '.')) != NULL)
240  *p = '\0';
241  else
242  break;
243  }
244  goto host_check_ok;
245  }
246 
247  if (zeStrRegex(domain, IPV6_ADDR_REGEX, NULL, NULL, TRUE)) {
248  ipv6_T ipv6;
249  char buf[256];
250 
251  snprintf(k, sizeof (k), "%s:%s", prefix, domain);
252  ZE_MessageInfo(DBG_LEVEL, "IP : Looking for %s ...", k);
253  if (zeDb_GetRec(&hdb, k, v, sizeof (v))) {
254  if ((bufout != NULL) && (size > 0))
255  strlcpy(bufout, v, size);
256  ZE_MessageInfo(DBG_LEVEL, " : Found %s %s...", k, v);
257  found = TRUE;
258  goto host_check_ok;
259  }
260 
261  if (ipv6_str2rec(&ipv6, domain)) {
262  int hi, lo, step, i;
263 
264  hi = IPV6_PREFIX_MAX;
265  lo = IPV6_PREFIX_MIN;
266  step = IPV6_PREFIX_STEP;
267 
268  ipv6_rec2str(buf, &ipv6, sizeof (buf));
269  snprintf(k, sizeof (k), "%s:%s", prefix, buf);
270  ZE_MessageInfo(DBG_LEVEL, "IP : Looking for %s ...", k);
271  if (zeDb_GetRec(&hdb, k, v, sizeof (v))) {
272  if ((bufout != NULL) && (size > 0))
273  strlcpy(bufout, v, size);
274  ZE_MessageInfo(DBG_LEVEL, " : Found %s %s...", k, v);
275  found = TRUE;
276  goto host_check_ok;
277  }
278 
279  for (i = IPV6_PREFIX_MAX; i >= IPV6_PREFIX_MIN; i -= IPV6_PREFIX_STEP) {
280 #if 1
281  ipv6_prefix_str(&ipv6, buf, sizeof (buf), i);
282 #else
283  ipv6_T ip, net;
284 
285  ip = ipv6;
286  ipv6_set_prefix(&ip, i);
287  ipv6_subnet(&net, &ip);
288  ipv6_rec2str(buf, &net, sizeof (buf));
289 #endif
290  snprintf(k, sizeof (k), "%s:%s", prefix, buf);
291  ZE_MessageInfo(DBG_LEVEL, "IP : Looking for %s ...", k);
292  if (zeDb_GetRec(&hdb, k, v, sizeof (v))) {
293  if ((bufout != NULL) && (size > 0))
294  strlcpy(bufout, v, size);
295  ZE_MessageInfo(DBG_LEVEL, " : Found %s %s...", k, v);
296  found = TRUE;
297  goto host_check_ok;
298  }
299  }
300  }
301 
302  goto host_check_ok;
303  }
304 
305  {
306  /*
307  * This is a domain name
308  */
309  /*
310  * Try each part beginning from the most complete one
311  */
312  p = domain;
313  while (p != NULL && strlen(p) > 0) {
314  snprintf(k, sizeof (k), "%s:%s", prefix, p);
315  (void) zeStr2Lower(k);
316  ZE_MessageInfo(DBG_LEVEL, "NAME : Looking for %s", k);
317  if (zeDb_GetRec(&hdb, k, v, sizeof (v))) {
318  if ((bufout != NULL) && (size > 0))
319  strlcpy(bufout, v, size);
320  ZE_MessageInfo(DBG_LEVEL, " : Found %s %s...", k, v);
321  found = TRUE;
322  break;
323  }
324  p = strchr(p, '.');
325  if (p != NULL)
326  p++;
327  }
328  }
329 
330 host_check_ok:
331  if (found)
332  goto fin;
333 
334  /*
335  * Entire key doesn't match - lets check user part
336  */
337  if (is_email) {
338  char *p;
339 
340  snprintf(k, sizeof (k), "%s:%s", prefix, email);
341  (void) zeStr2Lower(k);
342  p = strchr(k, '@');
343  if (p != NULL)
344  *(++p) = '\0';
345 
346  ZE_MessageInfo(DBG_LEVEL, "k = %s", k);
347 
348  if (zeDb_GetRec(&hdb, k, v, sizeof (v))) {
349  if ((bufout != NULL) && (size > 0))
350  strlcpy(bufout, v, size);
351 
352  found = TRUE;
353  goto fin;
354  }
355  }
356 
357 fin:
358  FREE(email);
359  zeDb_Unlock(&hdb);
360 
361  return found;
362 }
363 
364 /* ****************************************************************************
365  * *
366  * *
367  **************************************************************************** */
368 
369 bool
370 db_policy_lookup(prefix, key, bufout, size)
371  char *prefix;
372  char *key;
373  char *bufout;
374  size_t size;
375 {
376  char k[256];
377  char v[1024];
378  bool found = FALSE;
379  static int nerr = 0;
380 
381  if (!zeDb_OK(&hdb) && !db_policy_open(TRUE)) {
382  if (nerr++ < MAX_ERR)
383  ZE_LogMsgError(0, "Can't open policy database");
384  return FALSE;
385  }
386 
387  if (key == NULL)
388  return FALSE;
389 
390  if (key == NULL || strlen(key) == 0)
391  key = "default";
392 
393 
394  zeDb_Lock(&hdb);
395  nerr = 0;
396  /*
397  * First of all, let's check the entire key
398  */
399  snprintf(k, sizeof (k), "%s:%s", prefix, key);
400  (void) zeStr2Lower(k);
401  ZE_MessageInfo(DBG_LEVEL, "KEY FULL : Looking for %s ...", k);
402  if (zeDb_GetRec(&hdb, k, v, sizeof (v))) {
403  if ((bufout != NULL) && (size > 0))
404  strlcpy(bufout, v, size);
405  ZE_MessageInfo(DBG_LEVEL, " : Found %s %s...", k, v);
406  found = TRUE;
407  goto fin;
408  }
409 
410 fin:
411  zeDb_Unlock(&hdb);
412 
413  if (getenv("SHOWLOOKUP") != NULL)
414  ZE_MessageInfo(0, "%-40s %s", k, found ? bufout : "");
415 
416  return found;
417 }
Definition: ze-ipv6.h:32
bool zeDb_Unlock(ZEDB_T *h)
Database unlock.
Definition: zeDb.c:907
#define CF_CDBDIR
Definition: cfh-defs.h:78
#define strrchr
Definition: ze-sys.h:219
bool zeDb_OK(ZEDB_T *h)
Definition: zeDb.c:649
#define FREE(x)
Definition: macros.h:37
#define ZE_CDBDIR
Definition: defs.h:34
Definition: zeDb.h:47
#define IPV6_ADDR_REGEX
Definition: macros.h:219
bool db_policy_lookup(char *prefix, char *key, char *bufout, size_t size)
Definition: ze-dbpolicy.c:370
#define FALSE
Definition: macros.h:160
#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
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
char * extract_email_address(char *, char *, size_t)
bool db_policy_reopen()
Definition: ze-dbpolicy.c:82
#define IPV6_PREFIX_STEP
Definition: ze-ipv6.h:56
#define strchr
Definition: ze-sys.h:218
void ipv6_set_prefix(ipv6_T *addr, int prefix)
Definition: ze-ipv6.c:242
#define CF_DB_POLICY
Definition: cfh-defs.h:80
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
bool db_policy_close()
Definition: ze-dbpolicy.c:105
bool zeDb_Close(ZEDB_T *h)
Definition: zeDb.c:667
bool db_policy_check(char *prefix, char *key, char *bufout, size_t size)
Definition: ze-dbpolicy.c:141
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
bool db_policy_open(bool rd)
Definition: ze-dbpolicy.c:44
bool zeDb_GetRec(ZEDB_T *h, char *, void *, size_t)
Definition: zeDb.c:791
#define TRUE
Definition: macros.h:157
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
char * cf_get_str(int id)
Definition: ze-cf.c:854
char * zeStr2Lower(char *)
Definition: zeStrings.c:295
#define IPV6_PREFIX_MIN
Definition: ze-ipv6.h:55
void ipv6_subnet(ipv6_T *net, ipv6_T *addr)
Definition: ze-ipv6.c:270
void ipv6_prefix_str(ipv6_T *addr, char *buf, size_t size, int n)
Definition: ze-ipv6.c:290
void ipv6_rec2str(char *sout, ipv6_T *ipv6, size_t sz)
Definition: ze-ipv6.c:210
#define IPV4_ADDR_REGEX
Definition: macros.h:218
#define MAX_ERR
Definition: ze-dbpolicy.c:124
#define ZEDB_INITIALIZER
Definition: zeDb.h:111
char domain[]
#define IPV6_PREFIX_MAX
Definition: ze-ipv6.h:54
#define DBG_LEVEL
Definition: ze-dbpolicy.c:138
bool zeDb_Lock(ZEDB_T *h)
Database lock.
Definition: zeDb.c:896