source: npl/mailserver/dspam/dspam-3.10.2/src/tools/dspam_clean.c @ c5c522c

gcc484ntopperl-5.22
Last change on this file since c5c522c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 12.2 KB
Line 
1/* $Id: dspam_clean.c,v 1.247 2011/06/28 00:13:48 sbajic Exp $ */
2
3/*
4 DSPAM
5 COPYRIGHT (C) 2002-2012 DSPAM PROJECT
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Affero General Public License as
9 published by the Free Software Foundation, either version 3 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU Affero General Public License for more details.
16
17 You should have received a copy of the GNU Affero General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20*/
21
22#ifdef HAVE_CONFIG_H
23#include <auto-config.h>
24#endif
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <dirent.h>
30#include <ctype.h>
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <errno.h>
34#include <fcntl.h>
35#include <signal.h>
36
37#ifdef TIME_WITH_SYS_TIME
38#   include <sys/time.h>
39#   include <time.h>
40#else
41#   ifdef HAVE_SYS_TIME_H
42#       include <sys/time.h>
43#   else
44#       include <time.h>
45#   endif
46#endif
47
48#include "libdspam.h"
49#include "language.h"
50#include "read_config.h"
51#include "config_api.h"
52#include "pref.h"
53#include "error.h"
54
55DSPAM_CTX *open_ctx = NULL, *open_mtx = NULL;
56
57int process_sigs   (DSPAM_CTX * CTX, int age);
58int process_probs  (DSPAM_CTX * CTX, int age);
59int process_unused (DSPAM_CTX * CTX, int any, int quota, int nospam, int onehit);
60void dieout (int signal);
61
62#define CLEANSYNTAX "dspam_clean [-s[age] -p[age] -u[any,hapax,nospam,onehit] -h] [user1 user2 ... userN]\n"
63
64int
65main (int argc, char *argv[])
66{
67  DSPAM_CTX *CTX = NULL, *CTX2;
68  char *user;
69  int do_sigs   = 0;
70  int do_probs  = 0;
71  int do_unused = 0;
72  int age_sigs   = 14;
73  int age_probs  = 30;
74  int age_unused[4] = { 90, 30, 15, 15 };
75  int i, help = 0;
76  struct nt *users = NULL;
77  struct nt_node *node = NULL;
78#ifndef _WIN32
79#ifdef TRUSTED_USER_SECURITY
80  struct passwd *p = getpwuid (getuid ());
81
82#endif
83#endif
84
85 /* Read dspam.conf */
86                                                                               
87  agent_config = read_config(NULL);
88  if (!agent_config) {
89    LOG(LOG_ERR, ERR_AGENT_READ_CONFIG);
90    fprintf (stderr, ERR_AGENT_READ_CONFIG "\n");
91    exit(EXIT_FAILURE);
92  }
93                                                                               
94  if (!_ds_read_attribute(agent_config, "Home")) {
95    LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME);
96    fprintf (stderr, ERR_AGENT_DSPAM_HOME "\n");
97    goto bail;
98  }
99                                                                               
100  if (libdspam_init(_ds_read_attribute(agent_config, "StorageDriver")) != 0) {
101    LOG(LOG_ERR, ERR_DRV_INIT);
102    fprintf (stderr, ERR_DRV_INIT "\n");
103    _ds_destroy_config(agent_config);
104    exit(EXIT_FAILURE);
105  }
106
107#ifndef _WIN32
108#ifdef TRUSTED_USER_SECURITY
109  if (!_ds_match_attribute(agent_config, "Trust", p->pw_name) && p->pw_uid) {
110    fprintf(stderr, ERR_TRUSTED_MODE "\n");
111    goto bail;
112  }
113#endif
114#endif
115
116  for(i=0;i<argc;i++) {
117                                                                               
118    if (!strncmp (argv[i], "--profile=", 10))
119    {
120      if (!_ds_match_attribute(agent_config, "Profile", argv[i]+10)) {
121        LOG(LOG_ERR, ERR_AGENT_NO_SUCH_PROFILE, argv[i]+10);
122        fprintf (stderr, ERR_AGENT_NO_SUCH_PROFILE "\n", argv[i]+10);
123        goto bail;
124      } else {
125        _ds_overwrite_attribute(agent_config, "DefaultProfile", argv[i]+10);
126      }
127      break;
128    }
129  }
130
131#ifdef DEBUG
132  fprintf (stdout, "dspam_clean starting\n");
133#endif
134
135  if (_ds_read_attribute(agent_config, "PurgeSignatures") &&
136      !_ds_match_attribute(agent_config, "PurgeSignatures", "off")) 
137  {
138    do_sigs = 1;
139    age_sigs = atoi(_ds_read_attribute(agent_config, "PurgeSignatures"));
140  }
141 
142  if (_ds_read_attribute(agent_config, "PurgeNeutral") &&
143      !_ds_match_attribute(agent_config, "PurgeNeutral", "off"))
144  {
145    do_probs = 1;
146    age_probs = atoi(_ds_read_attribute(agent_config, "PurgeNeutral"));
147  }
148
149  if (_ds_read_attribute(agent_config, "PurgeUnused") &&
150      !_ds_match_attribute(agent_config, "PurgeUnused", "off"))
151  {
152    int i;
153
154    do_unused = 1;
155    age_unused[0] = atoi(_ds_read_attribute(agent_config, "PurgeUnused"));
156    age_unused[1] = atoi(_ds_read_attribute(agent_config, "PurgeHapaxes"));
157    age_unused[2] = atoi(_ds_read_attribute(agent_config, "PurgeHits1S"));
158    age_unused[3] = atoi(_ds_read_attribute(agent_config, "PurgeHits1I"));
159
160    for(i=0;i<4;i++)
161      if (age_unused[i]==0)
162        do_unused = 0;
163  }
164
165  users = nt_create(NT_CHAR);
166  if (users == NULL) {
167    fprintf(stderr, "%s", ERR_MEM_ALLOC);
168    goto bail;
169  }
170
171  for(i=0;i<argc;i++) {
172    if (!strncmp(argv[i], "-p", 2)) {
173      do_probs = 1;
174      if (strlen(argv[i])>2)
175        age_probs = atoi(argv[i]+2);
176    }
177    else if (!strncmp(argv[i], "-s", 2)) {
178      do_sigs = 1;
179      if (strlen(argv[i])>2)
180        age_sigs = atoi(argv[i]+2);
181    } else if (!strncmp(argv[i], "-u", 2)) {
182      do_unused = 1;
183      if (strlen(argv[i])>2) {
184        char *c = strdup(argv[i]+2);
185        char *d = strtok(c, ",");
186        int j = 0;
187        while(d != NULL && j<4) {
188          age_unused[j] = atoi(d);
189          j++;
190          d = strtok(NULL, ",");
191        }
192        free(c);
193      }
194    }
195    else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
196      help = 1;
197    else if (i>0)
198      nt_add(users, argv[i]);
199  }
200
201  if (help || (!do_probs && !do_sigs && !do_unused)) {
202    fprintf(stderr, "%s", CLEANSYNTAX);
203    _ds_destroy_config(agent_config);
204    nt_destroy(users);
205    libdspam_shutdown();
206    if (help) {
207      exit(EXIT_SUCCESS);
208    }
209    exit(EXIT_FAILURE);
210  }
211     
212  open_ctx = open_mtx = NULL;
213
214  signal (SIGINT, dieout);
215  signal (SIGPIPE, dieout);
216  signal (SIGTERM, dieout);
217
218  dspam_init_driver (NULL);
219
220  if (users->items == 0) {
221    CTX = dspam_create (NULL, NULL, _ds_read_attribute(agent_config, "Home"), DSM_TOOLS, 0);
222    open_ctx = CTX;
223    if (CTX == NULL)
224    {
225      fprintf (stderr, "Could not initialize context: %s\n", strerror (errno));
226      dspam_shutdown_driver (NULL);
227      goto bail;
228    }
229
230    set_libdspam_attributes(CTX);
231    if (dspam_attach(CTX, NULL)) {
232      LOG (LOG_WARNING, "unable to attach dspam context");
233      fprintf (stderr, "Unable to attach DSPAM context\n");
234      goto bail;
235    }
236
237    user = _ds_get_nextuser (CTX);
238  } else {
239    node = users->first;
240    if (node != NULL)
241      user = node->ptr;
242    else
243      goto bail;
244  }
245
246  while (user != NULL)
247  {
248#ifdef DEBUG
249    printf ("PROCESSING USER: %s\n", user);
250#endif
251    CTX2 = dspam_create (user, NULL,  _ds_read_attribute(agent_config, "Home"), DSM_TOOLS, 0);
252    open_mtx = CTX2;
253
254    if (CTX2 == NULL)
255    {
256      fprintf (stderr, "Could not initialize context: %s\n",
257               strerror (errno));
258      return EUNKNOWN;
259    }
260
261    set_libdspam_attributes(CTX2);
262    if (dspam_attach(CTX2, NULL)) {
263      LOG (LOG_WARNING, "unable to attach dspam context");
264      fprintf (stderr, "Unable to attach DSPAM context\n");
265      goto bail;
266    }
267
268    if (do_sigs)
269      process_sigs(CTX2, age_sigs);
270    if (do_probs)
271      process_probs(CTX2, age_probs);
272    if (do_unused)
273      process_unused(CTX2, age_unused[0], age_unused[1], age_unused[2], age_unused[3]);
274    dspam_destroy (CTX2);
275    open_mtx = NULL;
276
277    if (users->items == 0) {
278      user = _ds_get_nextuser (CTX);
279    } else {
280      if (node == NULL || node->next == NULL) {
281        node = NULL;
282        user = NULL;
283      } else {
284        node = node->next;
285        user = node->ptr;
286      }
287    }
288  }
289
290  if (users->items == 0) {
291    dspam_destroy (CTX);
292    open_ctx = NULL;
293  }
294
295  dspam_shutdown_driver (NULL);
296  _ds_destroy_config(agent_config);
297  nt_destroy(users);
298  libdspam_shutdown();
299  exit (EXIT_SUCCESS);
300
301bail:
302
303  if (open_ctx)
304    dspam_destroy(open_ctx);
305  if (open_mtx)
306    dspam_destroy(open_mtx);
307  _ds_destroy_config(agent_config);
308  nt_destroy(users);
309  libdspam_shutdown();
310  exit(EXIT_FAILURE);
311}
312
313int
314process_sigs (DSPAM_CTX * CTX, int age)
315{
316  struct _ds_storage_signature *ss;
317  struct nt *del;
318  struct nt_node *node;
319  int delta;
320
321  del = nt_create(NT_CHAR);
322  if (del == NULL)
323    return -1;
324
325#ifdef DEBUG
326    printf ("Processing sigs; age: %d\n", age);
327#endif
328
329  ss = _ds_get_nextsignature (CTX);
330  while (ss != NULL)
331  {
332#ifdef DEBUG
333    printf ("Signature: %s\n    Created: %s\n", ss->signature,
334            ctime (&ss->created_on));
335#endif
336    delta = (((time (NULL) - ss->created_on) / 60) / 60) / 24;
337    if (age == 0 || delta > age)
338    {
339#ifdef DEBUG
340      printf ("    DELETED!\n");
341#endif
342      nt_add(del, ss->signature);
343    }
344    free(ss->data);
345    free(ss);
346    ss = _ds_get_nextsignature (CTX);
347  }
348
349  node = del->first;
350  while(node != NULL) {
351    _ds_delete_signature (CTX, node->ptr);
352    node = node->next;
353  }
354  nt_destroy(del);
355
356  return 0;
357}
358
359int process_probs (DSPAM_CTX *CTX, int age) {
360  struct _ds_storage_record *sr;
361  struct _ds_spam_stat s;
362  ds_diction_t del;
363  int delta;
364
365#ifdef DEBUG
366  printf("Processing probabilities; age: %d\n", age);
367#endif
368
369  del = ds_diction_create(196613);
370  if (del == NULL)
371    return -1;
372  sr = _ds_get_nexttoken (CTX);
373  while (sr != NULL)
374  {
375    s.innocent_hits = sr->innocent_hits;
376    s.spam_hits = sr->spam_hits;
377    s.probability = 0.00000;
378    _ds_calc_stat(CTX, NULL, &s, DTT_DEFAULT, NULL);
379    if (s.probability >= 0.3500 && s.probability <= 0.6500) {
380      delta = (((time (NULL) - sr->last_hit) / 60) / 60) / 24;
381      if (age == 0 || delta > age)
382        ds_diction_touch(del, sr->token, "", 0);
383    }
384    free (sr);
385    sr = _ds_get_nexttoken (CTX);
386  }
387 
388  _ds_delall_spamrecords(CTX, del);
389  ds_diction_destroy(del);
390
391  return 0;
392}
393
394int process_unused (DSPAM_CTX *CTX, int any, int quota, int nospam, int onehit) {
395  struct _ds_storage_record *sr;
396  ds_diction_t del;
397  time_t t = time(NULL);
398  int delta, toe = 0, tum = 0;
399  agent_pref_t PTX;
400                                                                               
401#ifdef DEBUG
402  printf("Processing unused; any: %d quota: %d nospam: %d onehit: %d\n",
403         any, quota, nospam, onehit);
404#endif
405
406  PTX = _ds_pref_load(agent_config, CTX->username, _ds_read_attribute(agent_config, "Home"), NULL);
407
408  if (PTX == NULL || PTX[0] == 0) {
409    if (PTX)
410      _ds_pref_free(PTX);
411    PTX = pref_config();
412  }
413                                                                               
414  if (!strcasecmp(_ds_pref_val(PTX, "trainingMode"), "toe")) {
415#ifdef DEBUG
416    printf("Limiting unused token purges for user %s - TOE Training Mode Set\n", CTX->username);
417#endif
418    toe = 1;
419  }
420
421  if (!strcasecmp(_ds_pref_val(PTX, "trainingMode"), "tum")) {
422#ifdef DEBUG
423    printf("Limiting unused token purges for user %s - TUM Training Mode Set\n", CTX->username);
424#endif
425    tum = 1;
426  }
427
428  if (PTX)
429    _ds_pref_free(PTX);
430
431  del = ds_diction_create(196613);
432  if (del == NULL)
433    return -1;
434  sr = _ds_get_nexttoken (CTX);
435  while (sr != NULL)
436  {
437    delta = (((t - sr->last_hit) / 60) / 60) / 24;
438    if (!toe && (any == 0 || delta > any))
439    {
440      if (!tum || sr->innocent_hits + sr->spam_hits < 50)
441        ds_diction_touch(del, sr->token, "", 0);
442    }
443    else if ((sr->innocent_hits*2) + sr->spam_hits < 5)
444    {
445      if (quota == 0 || delta > quota)
446      {
447        ds_diction_touch(del, sr->token, "", 0);
448      }
449      else if (sr->innocent_hits == 0 && sr->spam_hits == 1 &&
450          (nospam == 0 || delta > nospam))
451      {
452        ds_diction_touch(del, sr->token, "", 0);
453      }
454      else if (sr->innocent_hits == 1 && sr->spam_hits == 0 &&
455          (onehit == 0 || delta > onehit))
456      {
457        ds_diction_touch(del, sr->token, "", 0);
458      }
459    }
460 
461    free (sr);
462    sr = _ds_get_nexttoken (CTX);
463  }
464                                                                               
465  _ds_delall_spamrecords(CTX, del);
466  ds_diction_destroy(del);
467                                                                               
468  return 0;
469}
470
471void
472dieout (int signal)
473{
474  signal = signal; /* Keep compiler happy */
475  fprintf (stderr, "terminated.\n");
476  if (open_ctx != NULL)
477    dspam_destroy (open_ctx);
478  if (open_mtx != NULL)
479    dspam_destroy (open_mtx);
480  _ds_destroy_config(agent_config);
481  exit (EXIT_SUCCESS);
482}
Note: See TracBrowser for help on using the repository browser.