ze-filter  (ze-filter-0.8.0-develop-180218)
ze-greyd.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 
25 #include <ze-sys.h>
26 #include <libze.h>
27 #include <ze-filter.h>
28 
29 #define CTRL_TO 60000
30 #define CTRL_TO_NMAX 10
31 
32 #define GREY_SRV_CLOSE 1
33 #define GREY_SRV_OK 0
34 #define GREY_SRV_ERROR -1
35 #define GREY_IO_ERROR -2
36 
37 #define MAX_GREY_ERRORS 4
38 
39 static int handle_command(int, char *, int, char **);
40 
41 static void *greyd_father(void *);
42 
43 void *greyd_server(void *);
44 
45 static void usage(char *);
46 
47 static void remove_socket_file(void);
48 
49 #define USE_SIGACTION 1
50 
51 static void greyd_signal_handler(int);
52 
53 static bool set_uid_gid(char *, char *);
54 
55 static bool greyd_check_access(char *addr, char *name);
56 
57 /* ****************************************************************************
58  * *
59  * *
60  **************************************************************************** */
61 #define MAX_THREAD 64
62 
63 static int nthread = 0;
64 
65 static pthread_mutex_t smutex = PTHREAD_MUTEX_INITIALIZER;
66 
67 # define GREY_LOCK() \
68  if (pthread_mutex_lock(&smutex) != 0) { \
69  ZE_LogSysError("pthread_mutex_lock"); \
70  }
71 
72 # define GREY_UNLOCK() \
73  if (pthread_mutex_unlock(&smutex) != 0) { \
74  ZE_LogSysError("pthread_mutex_unlock"); \
75  }
76 
77 
78 struct confargs_T
79 {
80  char *user;
81  char *group;
82  int facility;
83  char *socket;
84 };
85 
86 typedef struct confargs_T confargs_T;
87 
88 static confargs_T cargs = {
89  NULL,
90  NULL,
91  LOG_LOCAL6,
92  NULL
93 };
94 
95 
96 static char *user = "ze-filter";
97 static char *group = "ze-filter";
98 
99 static char *workdir = ZE_GREYDDIR;
100 
101 #define DEFTUPLE "NET,HOST,FULL"
102 static char *ntuple = NULL;
103 
104 static char *tconst = NULL;
105 
106 #define MAX_ACCESS 256
107 static char *access_arr[MAX_ACCESS];
108 static char *access_str = NULL;
109 
110 int
111 main(argc, argv)
112  int argc;
113  char **argv;
114 {
115  int i;
116  bool foreground = FALSE;
117 
118  memset(access_arr, 0, sizeof (access_arr));
120 
121  ze_logLevel = 9;
122 
123  /*
124  ** 1. Read configuration parameters
125  */
126  {
127  const char *args = "ht:T:i:dvu:g:w:s:n:l:a:";
128  int c;
129 
130  while ((c = getopt(argc, argv, args)) != -1)
131  {
132  switch (c)
133  {
134  /* help */
135  case 'h':
136  usage(argv[0]);
137  exit(0);
138  break;
139 
140  case 'a':
141  access_str = optarg;
142  break;
143 
144  /* time constants */
145  case 't':
146  tconst = optarg;
147  break;
148 
149  /* database reload interval */
150  case 'i':
151  break;
152 
153  /* debug */
154  case 'd':
155  foreground = TRUE;
156  break;
157 
158  /* verbose */
159  case 'v':
160  ze_logLevel++;
161  break;
162 
163  /* user */
164  case 'u':
165  user = optarg;
166  break;
167 
168  /* group */
169  case 'g':
170  group = optarg;
171  break;
172 
173  /* group */
174  case 'l':
175  ze_logLevel = atoi(optarg);
176  break;
177 
178  /* Work directory */
179  case 'w':
180  workdir = optarg;
181  break;
182 
183  /* socket */
184  case 's':
185  FREE(cargs.socket);
186  if (zeStrRegex(optarg, "^inet:[0-9]+@[-a-z0-9.]+$", NULL, NULL, TRUE) ||
187  zeStrRegex(optarg, "^(local|unix):([-/a-z0-9.]+)+$", NULL, NULL,
188  TRUE))
189  {
190  cargs.socket = strdup(optarg);
191  if (cargs.socket == NULL)
192  ;
193  } else
194  ZE_MessageWarning(0, "Error : invalid parameter %s", optarg);
195  break;
196 
197  case 'n':
198  ntuple = optarg;
199  break;
200 
201  default:
202  usage(argv[0]);
203  printf("Error ... \n");
204  exit(0);
205  }
206  }
207  }
208 
209  configure("ze-greyd", conf_file, TRUE);
210 
211  /*
212  ** 2. Launch daemon
213  */
214  if (!foreground)
215  {
216  switch (fork())
217  {
218  case 0:
219  printf(" ze-greyd daemonized !\n");
220  break;
221  case -1:
222  perror(" Error daemonizing ze-greyd ");
223  exit(1);
224  break;
225  default:
226  exit(0);
227  }
228 
229  if (setpgid(0, 0) < 0)
230  ZE_LogSysError("Can't set process group leader");
231  signal(SIGHUP, SIG_IGN);
232  switch (fork())
233  {
234  case 0:
235  break;
236  case -1:
237  perror(" Error daemonizing ze-greyd ");
238  exit(1);
239  break;
240  default:
241  exit(0);
242  }
243 
244  {
245  int fd;
246 
247  if ((fd = open("/dev/null", O_RDONLY, 0)) < 0)
248  ZE_LogSysError("Can't open /dev/null read-only");
249 
250  if (dup2(fd, STDIN_FILENO) < 0)
251  ZE_LogSysError("Can't redirect stdin");
252 
253  close(fd);
254 
255  if ((fd = open("/dev/null", O_WRONLY, 0)) < 0)
256  ZE_LogSysError("Can't open /dev/null write-only");
257 
258  if (dup2(fd, STDOUT_FILENO) < 0)
259  ZE_LogSysError("Can't redirect stdout");
260 
261  if (dup2(fd, STDERR_FILENO) < 0)
262  ZE_LogSysError("Can't redirect stderr");
263 
264  close(fd);
265  }
266  }
267 
269 
270  {
271  char *dir = cf_get_str(CF_GREYDDIR);
272 
273  if (dir != NULL)
274  workdir = dir;
275  }
276 
277  zeLog_SetOutput(TRUE, foreground);
278 
279  (void) set_uid_gid(user, group);
280 
281  (void) policy_init();
282 
283  if (!open_work_db_env(workdir, workdir, FALSE))
284  {
285  return 1;
286  }
287 
288  if (!grey_init(workdir, FALSE, GREY_SERVER))
289  {
290  return 1;
291  }
292 
293  ntuple = STRNULL(ntuple, "NET,HOST,FULL");
294  if (ntuple != NULL)
295  {
296 #define NTP 3
297  int argc;
298  char *argv[NTP];
299  char *s = NULL;
300 
301  if ((s = strdup(ntuple)) != NULL)
302  {
303  memset(argv, 0, sizeof (argv));
304  argc = zeStr2Tokens(s, NTP, argv, ",");
305  for (i = 0; i < NTP; i++)
306  argv[i] = STRNULL(argv[i], "");
307  (void) grey_set_tuples(argv[0], argv[1], argv[2]);
308  }
309  }
310 
311  tconst = STRNULL(tconst, "0,0,0,0");
312  if (tconst != NULL)
313  {
314 #define NTC 4
315  int argc;
316  char *argv[NTC];
317  time_t tc[NTC];
318  char *s = NULL;
319 
320  if ((s = strdup(tconst)) != NULL)
321  {
322  memset(argv, 0, sizeof (argv));
323  memset(tc, 0, sizeof (tc));
324  argc = zeStr2Tokens(s, NTC, argv, ",");
325  for (i = 0; i < NTC; i++)
326  {
327  argv[i] = STRNULL(argv[i], "0");
328  tc[i] = zeStr2time(argv[i], NULL, 0);
329  }
330  (void) grey_set_delays(tc[0], tc[1], tc[2], tc[3]);
331  }
332  }
333 
334 
335  access_str = STRNULL(access_str, "127.0.0.1");
336  if (access_str != NULL)
337  {
338  int argc;
339  char *s = NULL;
340 
341  if ((s = strdup(access_str)) != NULL)
342  {
343  memset(access_arr, 0, sizeof (access_arr));
344  argc = zeStr2Tokens(s, MAX_ACCESS, access_arr, ",");
345  for (i = 0; i < MAX_ACCESS; i++)
346  access_arr[i] = STRNULL(access_arr[i], "UNKNOWN");
347  }
348  }
349 
350  greyd_father(NULL);
351 
352  return 0;
353 }
354 
355 typedef struct
356 {
357  char addr[64];
358  char name[256];
359  int sd;
360 } gclient_T;
361 
362 /* ****************************************************************************
363  * *
364  * *
365  **************************************************************************** */
366 #define SET_SIG_HANDLER(handler) \
367  do { \
368  struct sigaction act; \
369  \
370  memset(&act, 0, sizeof (act)); \
371  act.sa_handler = SIG_IGN; \
372  sigaction(SIGPIPE, &act, NULL); \
373  \
374  act.sa_handler = handler; \
375  sigaction(SIGINT, &act, NULL); \
376  sigaction(SIGTERM, &act, NULL); \
377  sigaction(SIGQUIT, &act, NULL); \
378  sigaction(SIGALRM, &act, NULL); \
379  sigaction(SIGHUP, &act, NULL); \
380  sigaction(SIGCHLD, &act, NULL); \
381  } while (0);
382 
383 
384 void *
385 greyd_father(arg)
386  void *arg;
387 {
388  int errs;
389  socklen_t addrlen, len;
390  int sockdomain;
391  int listenfd, connfd;
392  struct sockaddr *cliaddr;
393  char *p;
394  static time_t last_reload = 0;
395  server_T server;
396 
397  ZE_MessageInfo(9, "*** Starting %s ...", ZE_FUNCTION);
398 
399  last_reload = time(NULL);
400 
401 
402  atexit(remove_pid_file);
403  atexit(remove_socket_file);
404 
405 # if USE_SIGACTION
406 
407  SET_SIG_HANDLER(greyd_signal_handler);
408 
409 # else
410 
411  signal(SIGPIPE, SIG_IGN);
412  signal(SIGTERM, greyd_signal_handler);
413  signal(SIGQUIT, greyd_signal_handler);
414  signal(SIGHUP, greyd_signal_handler);
415  signal(SIGINT, greyd_signal_handler);
416  signal(SIGCHLD, greyd_signal_handler);
417  signal(SIGALRM, greyd_signal_handler);
418 
419 #endif
420 
421  if (cargs.socket == NULL)
423 
424  cargs.socket = STRNULL(cargs.socket, strdup("inet:2012@localhost"));
425 
426  if (cargs.socket == NULL)
427  {
428 
429  }
430  p = cargs.socket;
431 
432  memset(&server, 0, sizeof (server));
433  if ((listenfd = server_listen(p, &server)) < 0)
434  return NULL;
435 
436  addrlen = server.socklen;
437  sockdomain = server.family;
438 
439  errs = 0;
440 
441  if ((cliaddr = (struct sockaddr *) malloc(addrlen)) == NULL)
442  {
443  ZE_LogSysError("malloc(addrlen) error");
444  return NULL;
445  }
446 
447  for (;;)
448  {
449  int nerr = 0;
450  char client_addr[64], client_name[256];
451 
452  len = addrlen;
453  connfd = accept(listenfd, cliaddr, &len);
454 
455  if (connfd < 0)
456  continue;
457 
458  memset(client_addr, 0, sizeof (client_addr));
459  memset(client_name, 0, sizeof (client_name));
460 
461  if (sockdomain == AF_INET || sockdomain == AF_INET6)
462  {
463  char *addr, *name, *user;
464  bool ok = FALSE;
465  int i;
466 
467  addr = name = user = NULL;
468 
469  if (get_hostbysock(cliaddr, len, client_addr, sizeof (client_addr),
470  client_name, sizeof (client_name)))
471  {
472  addr = client_addr;
473  name = client_name;
474  }
475 
476  ZE_MessageInfo(9, "Connect from %s (%s)", STRNULL(addr, ""),
477  STRNULL(name, ""));
478 
479  ok = greyd_check_access(client_addr, client_name);
480  if (!ok)
481  {
482  for (i = 0; i < MAX_ACCESS; i++)
483  {
484  if (addr == NULL || access_arr[i] == NULL)
485  continue;
486 
487  ZE_MessageInfo(11, "Checking %s against %s",
488  STRNULL(addr, "--"), STRNULL(access_arr[i], "--"));
489 
490  if (strncasecmp(addr, access_arr[i], strlen(access_arr[i])) == 0)
491  {
492  ok = TRUE;
493  break;
494  }
495  }
496  }
497  if (!ok)
498  {
499  ZE_MessageInfo(9, "Access denied to %s (%s) on control channel",
500  STRNULL(addr, ""), STRNULL(name, ""));
501  (void) sd_printf(connfd, "500 Access denied\n");
502  shutdown(connfd, SHUT_RDWR);
503  close(connfd);
504  continue;
505  }
506  }
507 
508  /* launch greyd_server worker thread */
509  if (connfd >= 0)
510  {
511  pthread_t tid;
512  int r;
513  gclient_T *arg = NULL;
514 
515  if ((arg = malloc(sizeof (gclient_T))) == NULL)
516  {
517  ZE_LogSysError("Error creating server data structure");
518  (void) sd_printf(connfd, "421 System Error - come back later\n");
519  shutdown(connfd, SHUT_RDWR);
520  close(connfd);
521  if (nerr > 16)
522  break;
523  }
524 
525  arg->sd = connfd;
526  strlcpy(arg->addr, client_addr, sizeof (arg->addr));
527  strlcpy(arg->name, client_name, sizeof (arg->name));
528 
529  if ((r = pthread_create(&tid, NULL, greyd_server, arg)) != 0)
530  {
531  ZE_LogSysError("pthread_create error");
532  (void) sd_printf(connfd, "421 System Error - come back later\n");
533  shutdown(connfd, SHUT_RDWR);
534  close(connfd);
535  if (nerr > 16)
536  break;
537  } else
538  nerr = 0;
539  }
540  }
541 
542  FREE(cliaddr);
543 
544  return NULL;
545 }
546 
547 /* ****************************************************************************
548  * *
549  * *
550  **************************************************************************** */
551 #define MAX_ARGS 16
552 
553 void *
555  void *arg;
556 {
557  pthread_t tid;
558  int ntout = 0;
559  int neintr = 0;
560 
561  gclient_T *gclient = (gclient_T *) arg;
562  int fd;
563  char *addr;
564 
565  int r;
566  int nerrors = 0;
567 
568  int nloop = 0;
569  time_t tiloop = 0;
570 
571  ASSERT(gclient != NULL);
572  fd = gclient->sd;
573  addr = STRNULL(gclient->addr, "UNKNOWN");
574 
575  GREY_LOCK();
576  nthread++;
577  GREY_UNLOCK();
578 
579  tid = pthread_self();
580  pthread_detach(tid);
581 
582  if ((nthread < 0) || (nthread >= MAX_THREAD))
583  {
584  ZE_MessageWarning(9, "Too many threads ! ");
585  (void) sd_printf(fd, "421 I'm too busy. Come back later\r\n");
586  goto fin;
587  }
588 
589  if (!sd_printf(fd, "200 OK - Waiting for commands !\r\n"))
590  goto fin;
591 
592  tiloop = time(NULL);
593  nloop = 0;
594  for (;;)
595  {
596  if (nloop++ > 1000)
597  {
598  time_t now;
599 
600  now = time(NULL);
601  if (tiloop + 2 > now)
602  {
604  "PEER=(%s) Error : connection broken (looping) ! Closing connection !",
605  addr);
606  goto fin;
607  }
608  tiloop = now;
609  nloop = 0;
610  }
611 
612  r = jfd_ready(fd, ZE_SOCK_READ, CTRL_TO);
613 
614  if (r == ZE_SOCK_ERROR)
615  {
617  "PEER=(%s) Error : connection broken ! Closing connection !",
618  addr);
619  goto fin;
620  }
621 
622  if (r == ZE_SOCK_TIMEOUT)
623  {
624  long dt_max = 0, dt = 0;
625 
626  dt_max = cf_get_int(CF_GREYD_CLIENT_IDLE_MAX) * 1000;
627 
628  if (dt_max < CTRL_TO)
629  dt_max = CTRL_TO;
630 
631  ntout++;
632 
633  dt = ntout * CTRL_TO;
634 
635  if (dt >= dt_max)
636  {
637  ZE_MessageInfo(9,
638  "PEER=(%s) Connection inactive for more than %ld secs. Closing !",
639  addr, dt / 1000);
640  goto fin;
641  }
642  continue;
643  }
644 
645  ntout = 0;
646 
647  if (r == ZE_SOCK_READY)
648  {
649  char buf[1024];
650  size_t sz;
651 
652  memset(buf, 0, sizeof (buf));
653  if ((sz = recvfrom(fd, buf, sizeof (buf) - 1, 0, NULL, NULL)) > 0)
654  {
655  int r = GREY_SRV_OK;
656 
657  if (sz == 0)
658  {
659  ZE_MessageInfo(9, "PEER=(%s) Connection closed by peer", addr);
660  ZE_MessageWarning(9, "PEER=(%s) Empty received buffer", addr, buf);
661  continue;
662  }
663 
664  if (sz < 0)
665  {
666  if (errno == EINTR)
667  {
668  if (++neintr > 10)
669  {
670  ZE_MessageInfo(9, "PEER=(%s) Too many signals (EINTR)",
671  gclient->addr);
672  goto fin;
673  }
674  continue;
675  }
676 
677  ZE_MessageInfo(9, "PEER=(%s) Connection closed by peer", gclient->addr);
678  goto fin;
679  }
680 
681  neintr = 0;
682  arg = NULL;
683  zeStrChomp(buf);
684  zeStr2Lower(buf);
685 
686  ZE_MessageInfo(9, "PEER=(%s) CMD=(%s)", addr, buf);
687  if (strlen(buf) == 0) {
688  ZE_MessageWarning(9, "PEER=(%s) Empty command", addr, buf);
689  continue;
690  }
691 
692  /*
693  **
694  */
695  {
696  char *argv[MAX_ARGS];
697  int argc;
698 
699  argc = zeStr2Tokens(buf, MAX_ARGS, argv, " ,");
700 
701  r = handle_command(fd, addr, argc, argv);
702  if (r == GREY_SRV_OK)
703  {
704  nerrors = 0;
705  continue;
706  }
707  if (r == GREY_SRV_ERROR)
708  {
709  if (++nerrors > MAX_GREY_ERRORS)
710  goto fin;
711  continue;
712  }
713  if (r == GREY_IO_ERROR)
714  goto fin;
715  if (r == GREY_SRV_CLOSE)
716  goto fin;
717  }
718  }
719  }
720  break;
721  }
722 
723 fin:
724  shutdown(fd, SHUT_RDWR);
725  close(fd);
726 
727  GREY_LOCK();
728  nthread--;
729  GREY_UNLOCK();
730 
731  FREE(arg);
732 
733  ZE_MessageInfo(10, "PEER=(%s) Closing connection and handler", gclient->addr);
734 
735  return NULL;
736 }
737 
738 /* ****************************************************************************
739  * *
740  * *
741  **************************************************************************** */
742 static int
743 handle_command(sd, addr, argc, argv)
744  int sd;
745  char *addr;
746  int argc;
747  char **argv;
748 {
749  bool quit = FALSE;
750 
751  if (argv == NULL || argc == 0)
752  return GREY_SRV_ERROR;
753 
754  if (STRCASEEQUAL(argv[0], "quit") || STRCASEEQUAL(argv[0], "exit"))
755  {
756  if (argc > 1)
757  quit = TRUE;
758  }
759 
760  /*
761  **
762  */
763  if (STRCASEEQUAL(argv[0], "GREYCHECK"))
764  {
765  if (argc > 1)
766  {
767  int r = GREY_OK;
768  char *s = "OK";
769  bool new = FALSE;
770  bool can_validate = TRUE;
771 
772  char *ip = "", *from = "", *to = "", *hostname =
773  "", *netclass;
774 
775  ip = STRBOOL(argc > 1, argv[1], "-");
776  from = STRBOOL(argc > 2, argv[2], "-");
777  to = STRBOOL(argc > 3, argv[3], "-");
778  hostname = STRBOOL(argc > 4, argv[4], "-");
779  netclass = STRBOOL(argc > 5, argv[5], NULL);
780 
781  if (check_policy_tuple("GreyCheck", ip, hostname, NULL, from, to, FALSE))
782  {
783  r = grey_check(ip, from, to, hostname, &new, can_validate);
784  switch (r)
785  {
786  case GREY_OK:
787  s = "OK";
788  break;
789  case GREY_WAIT:
790  s = "WAIT";
791  break;
792  case GREY_ERROR:
793  s = "ERROR";
794  break;
795  case GREY_REJECT:
796  s = "REJECT";
797  break;
798  }
799  ZE_MessageInfo(9,
800  "PEER=(%s) ANSWER=(%d GREYCHECK - Grey server says... %s)",
801  addr, r, s);
802  } else
803  ZE_MessageInfo(9, "PEER=(%s) ANSWER=(%d GREYCHECK - policy says : %s)",
804  addr, r, s);
805 
806  if (!sd_printf
807  (sd, "%d GREYCHECK ANSWER Grey server said... %s \r\n", r, s))
808  goto ioerror;
809 
810  goto ok;
811  }
812 
813  if (!sd_printf(sd, "600 Not enough parameters !\r\n"))
814  goto ioerror;
815 
816  return GREY_SRV_ERROR;
817  }
818 
819  /*
820  **
821  */
822  if (STRCASEEQUAL(argv[0], "GREYVALID"))
823  {
824  char *ip = "", *from = "", *to = "", *hostname = "";
825 
826  ip = STRBOOL(argc > 1, argv[1], "-");
827  from = STRBOOL(argc > 2, argv[2], "-");
828  to = STRBOOL(argc > 3, argv[3], "-");
829  hostname = STRBOOL(argc > 4, argv[4], "-");
830 
831  if (argc > 1)
832  {
833  int r = GREY_OK;
834  char *s = NULL;
835 
836  r = grey_validate(ip, from, to, hostname);
837  switch (r)
838  {
839  case GREY_OK:
840  s = "OK";
841  break;
842  case GREY_ERROR:
843  s = "ERROR";
844  break;
845  }
846  ZE_MessageInfo(9, "PEER=(%s) ANSWER=(%d GREYVALID Grey server said... %s)",
847  addr, r, s);
848  if (!sd_printf
849  (sd, "%d GREYVALID ANSWER Grey server said... %s \r\n", r, s))
850  goto ioerror;
851 
852  goto ok;
853  }
854  if (!sd_printf(sd, "600 Not enough parameters !\r\n"))
855  goto ioerror;
856 
857  return GREY_SRV_ERROR;
858  }
859 
860  /*
861  **
862  **
863  */
864  if (STRCASEEQUAL(argv[0], "UPDATE"))
865  {
866  if (STRCASEEQUAL(argv[1], "PENDING"))
867  {
868  if (!sd_printf(sd, "200-OK for %s %s!\r\n", argv[0], argv[1]))
869  goto ioerror;
870 
871  if (!sd_printf(sd, "200 %s done !\r\n", argv[0]))
872  goto ioerror;
873 
874  goto ok;
875  }
876 
877  if (STRCASEEQUAL(argv[1], "VALID"))
878  {
879  if (!sd_printf(sd, "200-OK for %s %s!\r\n", argv[0], argv[1]))
880  goto ioerror;
881 
882  if (!sd_printf(sd, "200 %s done !\r\n", argv[0]))
883  goto ioerror;
884 
885  goto ok;
886  }
887 
888  return GREY_SRV_ERROR;
889  }
890 
891  /*
892  **
893  **
894  */
895  if (STRCASEEQUAL(argv[0], "UPLOAD"))
896  {
897  int nb = 0;
898 
899  if (STRCASEEQUAL(argv[1], "PENDING"))
900  {
901  if (!sd_printf(sd, "200-OK for %s %s!\r\n", argv[0], argv[1]))
902  goto ioerror;
903  nb = grey_dump(sd, argv[1], 21600);
904  if (!sd_printf(sd, "200 %s done !\r\n", argv[0]))
905  goto ioerror;
906 
907  goto ok;
908  }
909 
910  if (STRCASEEQUAL(argv[1], "VALID"))
911  {
912  if (!sd_printf(sd, "200-OK for %s %s!\r\n", argv[0], argv[1]))
913  goto ioerror;
914  nb = grey_dump(sd, argv[1], 21600);
915  if (!sd_printf(sd, "200 %s done !\r\n", argv[0]))
916  goto ioerror;
917 
918  goto ok;
919  }
920 
921  return GREY_SRV_ERROR;
922  }
923 
924  /*
925  **
926  **
927  */
928  if (STRCASEEQUAL(argv[0], "DOWNLOAD"))
929  {
930  int nb = 0;
931  time_t dt = 0;
932 
933  if (argc < 2)
934  return GREY_SRV_ERROR;
935 
936  if (argc > 2)
937  dt = zeStr2ulong(argv[2], NULL, 0);
938 
939  if (STRCASEEQUAL(argv[1], "PENDING"))
940  {
941  if (!sd_printf(sd, "200-OK for %s %s!\r\n", argv[0], argv[1]))
942  goto ioerror;
943  nb = grey_dump(sd, argv[1], dt);
944  if (!sd_printf(sd, "200 %s done !\r\n", argv[0]))
945  goto ioerror;
946 
947  goto ok;
948  }
949 
950  if (STRCASEEQUAL(argv[1], "VALID"))
951  {
952  if (!sd_printf(sd, "200-OK for %s %s!\r\n", argv[0], argv[1]))
953  goto ioerror;
954  nb = grey_dump(sd, argv[1], dt);
955  if (!sd_printf(sd, "200 %s done !\r\n", argv[0]))
956  goto ioerror;
957 
958  goto ok;
959  }
960 
961  if (STRCASEEQUAL(argv[1], "WHITE"))
962  {
963  if (!sd_printf(sd, "200-OK for %s %s!\r\n", argv[0], argv[1]))
964  goto ioerror;
965  nb = grey_dump(sd, argv[1], dt);
966  if (!sd_printf(sd, "200 %s done !\r\n", argv[0]))
967  goto ioerror;
968 
969  goto ok;
970  }
971 
972  return GREY_SRV_ERROR;
973  }
974 
975  /*
976  **
977  **
978  */
979  if (STRCASEEQUAL(argv[0], "RECONFIGURE"))
980  {
981  if (!sd_printf(sd, "200-OK for %s !\r\n", argv[0]))
982  goto ioerror;
983  configure("ze-greyd", conf_file, TRUE);
984  if (!sd_printf(sd, "200 %s done !\r\n", argv[0]))
985  goto ioerror;
986 
987  goto ok;
988  }
989 
990  /*
991  **
992  **
993  */
994  if (STRCASEEQUAL(argv[0], "REOPENDB"))
995  {
996  bool rok;
997 
998  if (!sd_printf(sd, "200-OK for %s !\r\n", argv[0]))
999  goto ioerror;
1000  rok = policy_reopen();
1001  if (!sd_printf(sd, "200 %s : %-10s %s !\r\n", argv[0], "POLICY",
1002  STRBOOL(rok, "OK", "ERROR")))
1003  goto ioerror;
1004 
1005  goto ok;
1006  }
1007 
1008  /*
1009  **
1010  **
1011  */
1012  if (STRCASEEQUAL(argv[0], "RESTART"))
1013  {
1014  if (!sd_printf(sd, "200-OK for %s !\r\n", argv[0]))
1015  goto ioerror;
1016  kill(0, SIGHUP);
1017  if (!sd_printf(sd, "200 %s done !\r\n", argv[0]))
1018  goto ioerror;
1019 
1020  goto ok;
1021  }
1022 
1023  /*
1024  **
1025  **
1026  */
1027  if (STRCASEEQUAL(argv[0], "HELP"))
1028  {
1029  if (!sd_printf(sd, "200-OK for %s !\r\n", argv[0]))
1030  goto ioerror;
1031 
1032  if (!sd_printf(sd, " GREYCHECK ip from to hostname\r\n"))
1033  goto ioerror;
1034  if (!sd_printf(sd, " GREYVALID ip from to hostname\r\n"))
1035  goto ioerror;
1036 
1037  if (!sd_printf(sd, " DOWNLOAD PENDING\r\n"))
1038  goto ioerror;
1039  if (!sd_printf(sd, " DOWNLOAD VALID\r\n"))
1040  goto ioerror;
1041 
1042  if (!sd_printf(sd, " UPDATE PENDING \r\n"))
1043  goto ioerror;
1044  if (!sd_printf(sd, " UPDATE VALID \r\n"))
1045  goto ioerror;
1046 
1047  if (!sd_printf(sd, " RECONFIGURE \r\n"))
1048  goto ioerror;
1049  if (!sd_printf(sd, " REOPENDB \r\n"))
1050  goto ioerror;
1051 
1052  if (!sd_printf(sd, " EXIT \r\n"))
1053  goto ioerror;
1054  if (!sd_printf(sd, " QUIT \r\n"))
1055  goto ioerror;
1056  if (!sd_printf(sd, " HELP \r\n"))
1057  goto ioerror;
1058  if (!sd_printf(sd, " SHUTDOWN \r\n"))
1059  goto ioerror;
1060 
1061 #if 0
1062  if (!sd_printf(sd, " \r\n"))
1063  goto ioerror;
1064  if (!sd_printf(sd, " \r\n"))
1065  goto ioerror;
1066  if (!sd_printf(sd, " \r\n"))
1067  goto ioerror;
1068  if (!sd_printf(sd, " \r\n"))
1069  goto ioerror;
1070 #endif
1071  if (!sd_printf(sd, "200 %s done !\r\n", argv[0]))
1072  goto ioerror;
1073 
1074  goto ok;
1075  }
1076 
1077  /*
1078  **
1079  **
1080  */
1081  if (STRCASEEQUAL(argv[0], "EXIT") || STRCASEEQUAL(argv[0], "QUIT"))
1082  {
1083 #if 1
1084  (void) sd_printf(sd, "200 OK for %s (EXIT)!\r\n", argv[0]);
1085 #endif
1086  return GREY_SRV_CLOSE;
1087  }
1088 
1089  /*
1090  **
1091  **
1092  */
1093  if (STRCASEEQUAL(argv[0], "SHUTDOWN"))
1094  {
1095  if (!sd_printf(sd, "200-OK for %s !\r\n", argv[0]))
1096  goto ioerror;
1097  kill(0, SIGTERM);
1098  if (!sd_printf(sd, "200 %s done (EXIT)!\r\n", argv[0]))
1099  goto ioerror;
1100 
1101  return GREY_SRV_CLOSE;
1102  }
1103 
1104  if (!sd_printf(sd, "600 %s : Unknown command !\r\n", argv[0]))
1105  goto ioerror;
1106 
1107  goto fin;
1108 
1109  /* I/O Error */
1110 ioerror:
1111  return GREY_IO_ERROR;
1112 
1113  /* Fin */
1114 fin:
1115  return GREY_SRV_ERROR;
1116 
1117  /* OK */
1118 ok:
1119  if (quit)
1120  {
1121  (void) sd_printf(sd, "200 OK for %s (EXIT)!\r\n", argv[0]);
1122  return GREY_SRV_CLOSE;
1123  }
1124  return GREY_SRV_OK;
1125 }
1126 
1127 /* ****************************************************************************
1128  * *
1129  * *
1130  **************************************************************************** */
1131 static bool
1132 greyd_check_access(addr, name)
1133  char *addr;
1134  char *name;
1135 {
1136  char buf[256];
1137  bool res = FALSE;
1138 
1139  addr = STRNULL(addr, "");
1140  name = STRNULL(name, "");
1141  ZE_MessageInfo(10, "Checking access for %s %s", addr, name);
1142  if (STREQUAL(addr, "127.0.0.1"))
1143  {
1144  res = TRUE;
1145  goto fin;
1146  }
1147  memset(buf, 0, sizeof (buf));
1148  if (check_policy("GreydAccess", addr, buf, sizeof (buf), FALSE))
1149  {
1150  ZE_MessageInfo(10, " ADDR %s found : %s", addr, buf);
1151  switch (policy_decode(buf))
1152  {
1153  case JC_OK:
1154  res = TRUE;
1155  break;
1156  case JC_REJECT:
1157  res = FALSE;
1158  break;
1159  }
1160  goto fin;
1161  }
1162  if (check_policy("GreydAccess", name, buf, sizeof (buf), TRUE))
1163  {
1164  ZE_MessageInfo(10, " NAME %s found : %s", name, buf);
1165  switch (policy_decode(buf))
1166  {
1167  case JC_OK:
1168  res = TRUE;
1169  break;
1170  case JC_REJECT:
1171  res = FALSE;
1172  break;
1173  }
1174  goto fin;
1175  }
1176 
1177 fin:
1178  if (!res)
1179  {
1181  "Control access denied for %s (%s) by access rules",
1182  STRNULL(addr, "UNKNOWN"), STRNULL(name, "UNKNOWN"));
1183  }
1184  return res;
1185 }
1186 
1187 /* ****************************************************************************
1188  * *
1189  * *
1190  **************************************************************************** */
1191 void
1192 usage(arg)
1193  char *arg;
1194 {
1195  printf("Usage : %s options\n"
1196  " %s\n"
1197  " Compiled on %s\n"
1198  " -h : this message\n"
1199  " -u : run ze-greyd as USER - default = ze-filter\n"
1200  " -g : run ze-greyd as GROUP - default = ze-filter\n"
1201  " -s : socket\n"
1202  " inet:2012@localhost\n"
1203  " local:/var/sock\n"
1204  " -a client access control : \"1.2.3.4,4.3.2.,11.22.33.44\"\n"
1205  " -n : ntuple definition : IP,FROM,TO\n"
1206  " IP = NONE | FULL | NET\n"
1207  " USER = NONE | FULL | USER | HOST\n"
1208  " TO = NONE | FULL | USER | HOST\n"
1209  " DEFAULT = NET,HOST,FULL\n"
1210  " -t : pending entries time constants : ta,tb,tc,td\n"
1211  " ta = Min Pending delay - normal senders\n"
1212  " tb = Max Pending delay - normal senders\n"
1213  " tc = Min Pending delay - null senders\n"
1214  " td = Max Pending delay - null senders\n"
1215  " -T : valid entries time constants : tv,tw,tb\n"
1216  " tv = valid entries lifetime\n"
1217  " tw = whitelisted entries lifetime\n"
1218  " tb = blacklisted entries lifetime\n"
1219  " -w : working directory : default = %s\n"
1220  " -t : \n"
1221  " -v : increase log level\n"
1222  " -d : debug mode - run in foreground\n"
1223  "\n"
1224  " " COPYRIGHT "\n"
1225  " Written by Jose Marcio Martins da Cruz\n"
1226  " Send bugs and gifts to jose.marcio.mc@gmail.org\n\n",
1227  arg, PACKAGE, __DATE__ " " __TIME__, ZE_GREYDDIR);
1228 }
1229 
1230 /* ****************************************************************************
1231  * *
1232  * *
1233  **************************************************************************** */
1234 static void
1235 remove_socket_file(void)
1236 {
1237  if (zeStrRegex(cargs.socket, "^(local|unix):", NULL, NULL, TRUE))
1238  {
1239  char *p = strchr(cargs.socket, ':');
1240  struct stat buf;
1241 
1242  if (p == NULL || *p == '\0')
1243  return;
1244  p++;
1245  if (*p == '\0')
1246  return;
1247  ZE_MessageInfo(0, "Removing socket %s", p);
1248  if (lstat(p, &buf) == 0)
1249  {
1250  ZE_MessageWarning(9, "Removing SOCK_FILE : %s", p);
1251  if (remove(p) != 0)
1252  ZE_LogSysError("Error removing socket");
1253  }
1254  }
1255 }
1256 
1257 
1258 /* ****************************************************************************
1259  * *
1260  * *
1261  **************************************************************************** */
1262 static void
1263 greyd_signal_handler(sig)
1264  int sig;
1265 {
1266 #if !USE_SIGACTION
1267  signal(sig, greyd_signal_handler);
1268 #endif
1269 
1270  switch (sig)
1271  {
1272  case SIGINT:
1273  case SIGTERM:
1274  case SIGQUIT:
1275  ZE_MessageInfo(9, "*** Exiting ze-greyd ...");
1276  exit(0);
1277  break;
1278  case SIGHUP:
1279  ZE_MessageInfo(9, "*** Reloading ze-greyd ...");
1280  break;
1281  case SIGALRM:
1282  ZE_MessageInfo(9, "*** SIGALRM signal ...");
1283  break;
1284  case SIGCHLD:
1285  {
1286  pid_t pid;
1287 
1288  while ((pid = WAIT_NOHANG(-1, NULL)) > 0)
1289  {
1290  int i;
1291 
1292  ZE_MessageInfo(10, "*** Child %ld terminated ...", (long) pid);
1293  }
1294  }
1295  break;
1296  default:
1297  break;
1298  }
1299 }
1300 
1301 
1302 /* ****************************************************************************
1303  * *
1304  * *
1305  **************************************************************************** */
1306 static bool
1307 set_uid_gid(user, group)
1308  char *user;
1309  char *group;
1310 {
1311  struct passwd *pw;
1312  struct group *gr;
1313 
1314  uid_t uid = getuid();
1315  gid_t gid = getgid();
1316 
1317  if ((gr = getgrnam(group)) != NULL)
1318  {
1319  ZE_LogMsgDebug(20, "GID DE %s : %ld", group, (long) gr->gr_gid);
1320  if (gid != gr->gr_gid)
1321  {
1322  if ((uid != 0) || (setregid(gr->gr_gid, gr->gr_gid) < 0))
1323  {
1324  ZE_LogSysError("Can't set process gid = %ld", (long) gr->gr_gid);
1325  return FALSE;
1326  }
1327  }
1328  }
1329 
1330  if ((pw = getpwnam(user)) != NULL)
1331  {
1332  ZE_LogMsgDebug(20, "UID DE %s : %ld", user, (long) pw->pw_uid);
1333  if (uid != pw->pw_uid)
1334  {
1335  if ((uid != 0) || (setreuid(pw->pw_uid, pw->pw_uid) < 0))
1336  {
1337  ZE_LogSysError("Can't set process uid = %ld", (long) pw->pw_uid);
1338  return FALSE;
1339  }
1340  }
1341  }
1342 
1343  return TRUE;
1344 }
#define MAX_ACCESS
Definition: ze-greyd.c:106
bool sd_printf(int sd, char *format,...)
Definition: ze-inet.c:629
char * socket
Definition: ze-greyd.c:83
#define CF_GREYD_CLIENT_IDLE_MAX
Definition: cfh-defs.h:216
#define GREY_LOCK()
Definition: ze-greyd.c:67
#define STRBOOL(x, t, f)
Definition: macros.h:87
char addr[64]
Definition: ze-greyd.c:357
int socklen_t
Definition: ze-sys.h:534
bool check_policy(char *prefix, char *key, char *buf, size_t size, bool cdef)
Definition: ze-policy.c:119
char name[256]
Definition: ze-greyd.c:358
char * user
Definition: ze-greyd.c:80
#define ASSERT(a)
Definition: macros.h:27
#define ZE_FUNCTION
Definition: ze-sys.h:471
bool grey_set_tuples(char *ip, char *from, char *to)
Definition: ze-grey.c:355
#define FREE(x)
Definition: macros.h:37
#define COPYRIGHT
Definition: version.h:31
#define NTP
int ze_logLevel
Definition: zeSyslog.c:34
#define STRNULL(x, r)
Definition: macros.h:81
bool ok
Definition: ze-connopen.c:59
bool grey_set_delays(time_t tp_min_norm, time_t tp_max_norm, time_t tp_min_null, time_t tp_max_null)
Definition: ze-grey.c:399
int jfd_ready(int, bool, long)
Definition: ze-inet.c:529
void zeLog_SetOutput(bool, bool)
Definition: zeSyslog.c:490
#define FALSE
Definition: macros.h:160
#define strlcpy
Definition: zeString.h:32
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
#define STREQUAL(a, b)
Definition: macros.h:78
#define GREY_ERROR
Definition: ze-grey.h:38
int sd
Definition: ze-greyd.c:359
#define GREY_REJECT
Definition: ze-grey.h:37
#define ZE_SOCK_TIMEOUT
Definition: ze-inet.h:62
bool policy_reopen()
Definition: ze-policy.c:712
bool open_work_db_env(char *defdir, char *cfdir, bool rdonly)
Definition: ze-databases.c:40
#define GREY_UNLOCK()
Definition: ze-greyd.c:72
#define CF_GREYD_SOCKET_LISTEN
Definition: cfh-defs.h:211
int grey_check(char *, char *, char *, char *, bool *, bool)
Definition: ze-grey.c:491
char * zeStrChomp(char *)
Definition: zeStrings.c:501
int facility
Definition: ze-greyd.c:82
#define WAIT_NOHANG(pid, stat)
Definition: macros.h:30
int cf_get_int(int id)
Definition: ze-cf.c:803
int zeStr2Tokens(char *, int, char **, char *)
Definition: zeStrings.c:610
#define MAX_GREY_ERRORS
Definition: ze-greyd.c:37
bool policy_init()
Definition: ze-policy.c:692
#define strchr
Definition: ze-sys.h:218
int policy_decode(char *)
Definition: ze-policy.c:722
int grey_validate(char *, char *, char *, char *)
Definition: ze-grey.c:825
char * group
Definition: ze-greyd.c:81
socklen_t socklen
Definition: ze-server.h:33
#define NTC
#define ZE_LogMsgDebug(level,...)
Definition: zeSyslog.h:109
bool get_hostbysock(struct sockaddr *sock, socklen_t slen, char *addr, size_t alen, char *name, size_t nlen)
Definition: ze-inet.c:421
#define GREY_OK
Definition: ze-grey.h:35
#define GREY_SRV_CLOSE
Definition: ze-greyd.c:32
int main(int argc, char **argv)
Definition: ze-greyd.c:111
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
#define CF_GREYDDIR
Definition: cfh-defs.h:214
bool grey_init(char *, bool, int)
Definition: ze-grey.c:1326
int nb
Definition: ze-connopen.c:61
#define MAX_THREAD
Definition: ze-greyd.c:61
#define TRUE
Definition: macros.h:157
#define ZE_MessageWarning(level,...)
Definition: zeSyslog.h:92
#define GREY_SERVER
Definition: ze-grey.h:52
bool create_pid_file(char *fname)
#define JC_OK
Definition: ze-policy.h:69
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
#define ZE_SOCK_ERROR
Definition: ze-inet.h:60
char * cf_get_str(int id)
Definition: ze-cf.c:854
char * conf_file
Definition: ze-cf.c:38
void * greyd_server(void *)
Definition: ze-greyd.c:554
#define GREY_WAIT
Definition: ze-grey.h:36
#define CTRL_TO
Definition: ze-greyd.c:29
int configure(char *, char *, bool)
Definition: ze-cf.c:1203
void usage(char *arg)
char * zeStr2Lower(char *)
Definition: zeStrings.c:295
#define ZE_GREYDDIR
Definition: defs.h:38
#define PACKAGE
Definition: version.h:28
int family
Definition: ze-server.h:30
#define STRCASEEQUAL(a, b)
Definition: macros.h:72
unsigned long zeStr2ulong(char *s, int *error, unsigned long dval)
Definition: zeStrConvert.c:100
#define MAX_ARGS
Definition: ze-greyd.c:551
#define GREY_SRV_OK
Definition: ze-greyd.c:33
#define ZE_SOCK_READ
Definition: ze-inet.h:57
int server_listen(char *spec, server_T *server)
Definition: ze-server.c:334
void remove_pid_file(void)
#define GREY_SRV_ERROR
Definition: ze-greyd.c:34
#define ZE_SOCK_READY
Definition: ze-inet.h:61
bool check_policy_tuple(char *prefix, char *ip, char *name, char *netclass, char *from, char *to, bool result)
Definition: ze-policy.c:277
int grey_dump(int fd, char *which, time_t dt)
Definition: ze-grey.c:2685
#define GREY_IO_ERROR
Definition: ze-greyd.c:35
#define JC_REJECT
Definition: ze-policy.h:70
#define SET_SIG_HANDLER(handler)
Definition: ze-greyd.c:366
#define CF_GREYD_PID_FILE
Definition: cfh-defs.h:215
time_t zeStr2time(char *s, int *error, time_t dval)
Definition: zeStrConvert.c:291