source: trunk/src/sh_nmail.c @ 481

Last change on this file since 481 was 481, checked in by katerina, 6 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

File size: 22.3 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 2008 Rainer Wichmann                                      */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20#include "config_xor.h"
21
22#if defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
23#define _XOPEN_SOURCE 500
24#endif
25
26#if defined(GCC_VERSION_MAJOR) && !defined(__clang__)
27#if (GCC_VERSION_MAJOR > 4) || ((GCC_VERSION_MAJOR == 4) && (GCC_VERSION_MINOR > 8))
28#pragma GCC diagnostic ignored "-Wclobbered"
29#endif
30#endif
31
32#include <string.h>
33#include <time.h>
34
35#if defined(SH_WITH_MAIL)
36
37#undef  FIL__
38#define FIL__  _("sh_nmail.c")
39
40#include "samhain.h"
41#include "sh_pthread.h"
42#include "sh_mem.h"
43#include "sh_mail.h"
44#include "sh_tiger.h"
45#include "sh_string.h"
46#include "sh_utils.h"
47#include "sh_fifo.h"
48#include "sh_filter.h"
49#include "sh_mail_int.h"
50
51SH_MUTEX_INIT(mutex_listall, PTHREAD_MUTEX_INITIALIZER);
52SH_MUTEX_INIT(mutex_flush_l, PTHREAD_MUTEX_INITIALIZER);
53
54/* Pointer to last address */
55
56static struct alias * last = NULL;
57
58/* List of mail recipients */
59
60static struct alias * recipient_list = NULL;
61
62static struct alias * compiled_recipient_list = NULL;
63static sh_filter_type compiled_mail_filter = SH_FILT_INIT;
64
65/* List of mail aliases */
66
67static struct alias * alias_list = NULL;
68
69/* List of all recipients */
70
71struct alias * all_recipients = NULL;
72
73/* Check if addr is in list. If list is all_recipients,
74 * must iterate over ->all_next instead of ->next
75 */
76static int check_double (const char * str, struct alias * list, int isAll)
77{
78  if (str && list)
79    {
80      struct alias * item = list;
81
82      while (item)
83        {
84          if (0 == strcmp(sh_string_str(item->recipient), str))
85            return -1;
86          if (isAll)
87            item = item->all_next;
88          else
89            item = item->next;
90        }
91    }
92  return 0;
93}
94
95/* Add recipient to 'list' AND to all_recipients. If
96 * it already is in all_recipients, mark it as an alias
97 * (isAlias = 1).
98 */
99struct alias * add_recipient_intern(const char * str, 
100                                    struct alias * list)
101{
102  if (str)
103    {
104      struct alias * new  = SH_ALLOC(sizeof(struct alias));
105      new->next           = list;
106      new->mx_list        = NULL;
107      new->mail_filter    = NULL;
108      new->recipient_list = NULL;
109      new->severity       = (-1);
110      new->send_mail      = 0;
111      new->isAlias        = 0;
112      new->recipient      = sh_string_new_from_lchar(str, strlen(str));
113      list                = new;
114
115      SH_MUTEX_LOCK_UNSAFE(mutex_listall);
116      if (0 != check_double(str, all_recipients, S_TRUE))
117        {
118          new->isAlias    = 1;
119        }
120      new->all_next       = all_recipients;
121      all_recipients      = new;
122      SH_MUTEX_UNLOCK_UNSAFE(mutex_listall);
123    }
124  return list;
125}
126
127int sh_nmail_close_recipient(const char * str)
128{
129  (void) str;
130
131  if (last)
132    {
133      last = NULL;
134      return 0;
135    }
136  return -1;
137}
138
139/* Add a single recipient. Must not be in in
140 * recipient_list already, and not in all_recipients.
141 */
142int sh_nmail_add_recipient(const char * str)
143{
144  /* return error if duplicate, or
145   * already defined within an alias list.
146   */
147  if (0 == check_double(str,  recipient_list, S_FALSE) &&
148      0 == check_double(str,  all_recipients, S_TRUE))
149    {
150      recipient_list = add_recipient_intern(str, recipient_list);
151      last           = recipient_list;
152      return 0;
153    }
154  return -1;
155}
156
157/* Add a compiled-in address. These share the compiled_mail_filter
158 */
159int sh_nmail_add_compiled_recipient(const char * str)
160{
161  if (0 == check_double(str,  compiled_recipient_list, S_FALSE))
162    {
163      compiled_recipient_list = 
164        add_recipient_intern(str, compiled_recipient_list);
165      if (compiled_recipient_list)
166        compiled_recipient_list->mail_filter = &compiled_mail_filter;
167      last           = compiled_recipient_list;
168      return 0;
169    }
170  return -1;
171}
172
173/* Add an alias; format is name ":" comma-delimited_list_of_recipients
174 */
175int sh_nmail_add_alias(const char * str)
176{
177#define SH_ALIASES_RECP_NUM 256
178  size_t lengths[SH_ALIASES_RECP_NUM];
179  unsigned int    nfields = SH_ALIASES_RECP_NUM;
180  char * new = sh_util_strdup(str);
181  char * p   = strchr(new, ':');
182  char * q;
183
184  if (p && strlen(p) > 1)
185    {
186      unsigned int     i;
187      char ** array;
188
189      *p = '\0'; q = p; ++p;
190      if (strlen(new) > 0)
191        {
192          /* strip trailing space
193           */
194          --q; while ((q != new) && *q == ' ') { *q = '\0'; --q; }
195        }
196      else
197        {
198          goto err;
199        }
200
201      if (0 == check_double(new, alias_list, S_FALSE))
202        {
203          array = split_array_list(p, &nfields, lengths);
204
205          if (array && nfields > 0)
206            {
207              struct alias * newalias = NULL;
208
209              /* Enforce that all list members are defined already
210               */
211              int                nflag = 0;
212
213              for (i = 0; i < nfields; ++i) {
214                if (0 == check_double(array[i],  all_recipients, S_TRUE))
215                  nflag = 1; /* not in all_recipients --> bad */
216              }
217
218              if (nflag == 0)
219                {
220                  newalias                 = SH_ALLOC(sizeof(struct alias));
221                  newalias->recipient_list = NULL;
222                  newalias->mail_filter    = NULL;
223                  newalias->mx_list        = NULL;
224                  newalias->severity       = (-1);
225                 
226                  /* This is the alias */
227                  newalias->recipient = sh_string_new_from_lchar(new, strlen(new));
228                 
229                  for (i = 0; i < nfields; ++i)
230                    {
231                      if (lengths[i] > 0 && 
232                          0 == check_double(array[i], newalias->recipient_list, S_FALSE))
233                        {
234                          newalias->recipient_list = 
235                            add_recipient_intern(array[i], newalias->recipient_list);
236                        }
237                    }
238                }
239
240              SH_FREE(array);
241
242              if (newalias == NULL || newalias->recipient_list == NULL)
243                {
244                  if (newalias)
245                    SH_FREE(newalias);
246                  goto err;
247                }
248     
249              newalias->next = alias_list;
250              alias_list     = newalias;
251              last           = alias_list;
252
253              SH_FREE(new);
254              return 0;
255            }
256        }
257    }
258 err:
259  SH_FREE(new);
260  return -1;
261}
262
263
264/* <<<<<<<<<<<<<<< Recipient List >>>>>>>>>>>>>>>>>>>>>> */
265
266static struct alias * find_list (const char * alias, int * single)
267{
268  struct alias * list   = NULL;
269
270  *single = 0;
271
272  if (!alias)
273    {
274      list = all_recipients;
275    }
276  else
277    {
278      struct alias * test = alias_list;
279     
280      while (test)
281        {
282          if (0 == strcmp(alias, sh_string_str(test->recipient)))
283            {
284              list = test->recipient_list;
285              break;
286            }
287          test = test->next;
288        }
289     
290      if (!list)
291        {
292          test = recipient_list;
293          while (test)
294            {
295              if (0 == strcmp(alias, sh_string_str(test->recipient)))
296                {
297                  list   = test;
298                  *single = 1;
299                  break;
300                }
301              test = test->next;
302            }
303        }
304     
305      if (!list)
306        {
307          test = compiled_recipient_list;
308          while (test)
309            {
310              if (0 == strcmp(alias, sh_string_str(test->recipient)))
311                {
312                  list   = test;
313                  *single = 1;
314                  break;
315                }
316              test = test->next;
317            }
318        }
319    }
320  return list;
321}
322
323/* Returns zero (no) or one (yes). Used to tag messages that are
324 * valid for a given recipient (or mailing list alias).
325 */
326int sh_nmail_valid_message_for_alias (int level, 
327                                      const char * message, 
328                                      const char * alias, 
329                                      const void * rcv_info)
330{
331  const struct alias * rcv = (const struct alias *) rcv_info;
332
333  if (!alias || 0 == strcmp(alias, sh_string_str(rcv->recipient)))
334    {
335      if ((level & rcv->severity) == 0)
336        {
337          return 0;
338        }
339
340      if (rcv->mail_filter)
341        {
342          if (0 != sh_filter_filter(message, rcv->mail_filter))
343            {
344              return 0;
345            }
346        }
347    }
348
349  return 1;
350}
351
352/* Returns number of recipients */
353
354static
355int sh_nmail_compute_recipients (int level, const char * message, 
356                                 const char * alias, int flagit)
357{
358  struct alias * list   = NULL;
359  int            single = 0;
360  int            retval = 0;
361
362  if (flagit)
363    {
364      list = all_recipients;
365      while (list)
366        {
367          list->send_mail = 0;
368          list = list->all_next;
369        }
370      list = NULL;
371    }
372
373  if (message)
374    {
375      int flag = 0;
376
377      list = find_list (alias, &single);
378      if (list == all_recipients)
379        flag = 1;
380
381      while (list)
382        {
383          /* Check severity
384           */
385          if ((list->severity & level) == 0)
386            {
387              if (single) break;
388              if (flag)
389                list = list->all_next;
390              else
391                list = list->next;
392              continue;
393            }
394
395          /* Check filter
396           */
397          if (list->mail_filter &&
398              0 != sh_filter_filter(message, list->mail_filter))
399            {
400              if (single) break;
401              if (flag)
402                list = list->all_next;
403              else
404                list = list->next;
405              continue;
406            }
407         
408          /* Mark the entry
409           */
410          if (flag)
411            {
412              /* Don't mark aliases
413               */
414              if (flagit && list->isAlias == 0)
415                {
416                  list->send_mail = 1;
417                }
418              list = list->all_next;
419            }
420          else
421            {
422              if (flagit)
423                  list->send_mail = 1;
424              list = list->next;
425            }
426          ++retval;
427        }
428    }
429  return retval;
430}
431
432/* Is not called from same(recursively) or different thread
433 */
434static
435int sh_nmail_flag_recipients (int level, const char * message, 
436                              const char * alias)
437{
438  int retval = 0;
439
440  if (message)
441    {
442      SH_MUTEX_LOCK_UNSAFE(mutex_listall);
443      retval = sh_nmail_compute_recipients (level, message, alias, 1);
444      SH_MUTEX_UNLOCK_UNSAFE(mutex_listall);
445    }
446  return retval;
447}
448
449/* Can be called from same thread with mutex_listall held via sh_nmail_flush()
450 */
451static
452int sh_nmail_test_recipients (int level, const char * message, 
453                              const char * alias)
454{
455  int retval = 0;
456
457  if (message)
458    {
459      if (0 == SH_MUTEX_TRYLOCK_UNSAFE(mutex_flush_l))
460        {
461          SH_MUTEX_LOCK_UNSAFE(mutex_listall);
462          retval = sh_nmail_compute_recipients (level, message, alias, 0);
463          SH_MUTEX_UNLOCK_UNSAFE(mutex_listall);
464          SH_MUTEX_UNLOCK_UNSAFE(mutex_flush_l);
465        }
466    }
467  return retval;
468}
469
470/* <<<<<<<<<<<<<<<<<<<  Mail the message  >>>>>>>>>>>>>>>>>>>>>> */
471
472SH_MUTEX_RECURSIVE(mutex_nmail_msg);
473SH_MUTEX_STATIC(nmail_lock, PTHREAD_MUTEX_INITIALIZER);
474
475/*
476 * First test list of recipients, then call sh_mail_pushstack().
477 */
478int sh_nmail_pushstack (int level, const char * message, 
479                        const char * alias)
480{
481  int retval = 0;
482
483  if (0 != sh_nmail_test_recipients (level, message, alias))
484    {
485      retval = sh_mail_pushstack(level, message, alias);
486    }
487  return retval;
488}
489
490static int nmail_count = 0;
491
492/*
493 * First mark list of recipients, then call sh_mail_msg().
494 */
495int sh_nmail_msg (int level, const char * message, 
496                  const char * alias)
497{
498  volatile int retval = 0;
499
500  /* Need to:
501   *   -- wait if different thread, and
502   *   -- fail if same thread. */
503  SH_MUTEX_RECURSIVE_INIT(mutex_nmail_msg);
504  SH_MUTEX_RECURSIVE_LOCK(mutex_nmail_msg);
505
506  /* Only same thread beyond this point. We fail
507   * if count > 0 already. */
508  if (0 == SH_MUTEX_TRYLOCK_UNSAFE(nmail_lock))
509    {
510      ++nmail_count;
511      if (nmail_count != 1)
512        {
513          --nmail_count;
514          SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
515          goto cleanup;
516        }
517      SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
518
519      if (0 != sh_nmail_flag_recipients (level, message, alias))
520        {
521          /* Need to keep info for sh_nmail_pushstack()
522           */
523          SH_MUTEX_LOCK(mutex_listall);
524          retval = sh_mail_msg(message);
525          SH_MUTEX_UNLOCK(mutex_listall);
526
527          if (retval != 0)
528            {
529              sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 
530                               retval, MSG_E_SUBGEN,
531                               _("could not mail immediately"),
532                               _("sh_nmail_msg") );
533              sh_mail_pushstack(level, message, alias);
534            }
535        }
536      SH_MUTEX_LOCK_UNSAFE(nmail_lock);
537      --nmail_count;
538      SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
539    }
540 cleanup:
541  ; /* label at end of compound statement */
542  SH_MUTEX_RECURSIVE_UNLOCK(mutex_nmail_msg);
543  return retval;
544}
545
546static int sh_nmail_flush_int (void);
547
548int sh_nmail_flush ()
549{
550  int                retval = 0;
551
552  if (0 == SH_MUTEX_TRYLOCK_UNSAFE(nmail_lock))
553    {
554      ++nmail_count;
555      if (nmail_count != 1)
556        {
557          --nmail_count;
558          SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
559          return retval;
560        }
561      SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
562
563      retval = sh_nmail_flush_int ();
564
565      SH_MUTEX_LOCK_UNSAFE(nmail_lock);
566      --nmail_count;
567      SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
568    }
569  return retval;
570}
571
572/* warning: variable ‘list’ might be clobbered by ‘longjmp’ or ‘vfork’*/
573static struct alias ** list_dummy;
574
575/*
576 * Loop over all recipients in stack.
577 * For each distinct one, mark all messages for sending.
578 * Then call sh_mail_msg().
579 */
580
581static int sh_nmail_flush_int ()
582{
583  int                retval = 0;
584  sh_string *        msg    = NULL;
585  sh_string *        smsg   = NULL;
586  struct alias     * list;
587  struct alias     * dlist;
588
589  /* warning: variable ‘list’ might be clobbered by ‘longjmp’ or ‘vfork’*/
590  list_dummy = &list;
591
592  SH_MUTEX_LOCK(mutex_listall);
593
594  /* Reset recipient list
595   */
596  list = all_recipients;
597  while (list)
598    {
599      list->send_mail = 0;
600      list = list->all_next;
601    }
602
603  /* Check (i) compiled recipients, (b) aliases, (c) single recipients.
604   * For each, tag all messages, then call sh_mail_msg with
605   *  appropriate address list.
606   */
607
608  reset_list(fifo_mail);
609
610  /* Compiled recipients. These share threshold and filter,
611   * hence only the first recipient needs to be tested.
612   */
613  list  = compiled_recipient_list;
614
615  if (list)
616    {
617      msg   = tag_list(fifo_mail, sh_string_str(list->recipient),
618                       sh_nmail_valid_message_for_alias, list, S_TRUE);
619    }
620
621  if (msg)
622    {
623      while (list)
624        {
625          list->send_mail = 1;
626          list = list->next;
627        }
628     
629      list = compiled_recipient_list;
630     
631      SH_MUTEX_LOCK(mutex_flush_l);
632      (void) sh_mail_msg(sh_string_str(msg));
633      SH_MUTEX_UNLOCK(mutex_flush_l);
634
635      sh_string_destroy(&msg);
636     
637      list = compiled_recipient_list;
638      while (list)
639        {
640          list->send_mail = 0;
641          list = list->next;
642        }
643    }
644
645  /* Aliases
646   */
647  list  = alias_list;
648
649  while (list) {
650
651    /* Work through the recipient list. As smsg stores last msg,
652     * we send a batch whenever msg != smsg, and continue from
653     * that point in the recipient list.
654     */
655    struct alias     * lnew;
656
657    while (list)
658      {
659        msg   = tag_list(fifo_mail, sh_string_str(list->recipient),
660                         sh_nmail_valid_message_for_alias, list, S_FALSE);
661
662        if (msg)
663          {
664            if (!smsg) /* init */
665              {
666                smsg      = sh_string_copy(msg);
667              }
668            else
669              {
670                if (0 != strcmp(sh_string_str(smsg), sh_string_str(msg)))
671                  {
672                    /*
673                     * Don't set list = list->next here, since we want
674                     * to continue with this recipient in the next batch.
675                     */
676                    sh_string_destroy(&msg);
677                    break;
678                  }
679              }
680            lnew = list->recipient_list;
681            while (lnew)
682              {
683                lnew->send_mail = 1;
684                lnew= lnew->next;
685              }
686            sh_string_destroy(&msg);
687          }
688        list      = list->next;
689      }
690
691    /* Continue here if smsg != msg */
692
693    if (smsg)
694      {
695        SH_MUTEX_LOCK(mutex_flush_l);
696        (void) sh_mail_msg(sh_string_str(smsg));
697        SH_MUTEX_UNLOCK(mutex_flush_l);
698        sh_string_destroy(&smsg);
699      }
700
701    /* Reset old list of recipients (up to current point in list)
702     * and then continue with list from current point on.
703     */
704    dlist  = alias_list;
705    while (dlist)
706      {
707        lnew = dlist->recipient_list;
708        while (lnew)
709          {
710            lnew->send_mail = 0;
711            lnew = lnew->next;
712          }
713        dlist = dlist->next;
714      }
715  }
716
717
718  /* Single recipients
719   */
720  list  = recipient_list;
721
722  while (list) {
723
724    /* Work through the recipient list. As smsg stores last msg,
725     * we send a batch whenever msg != smsg, and continue from
726     * that point in the recipient list.
727     */
728
729    while (list)
730      {
731        msg   = tag_list(fifo_mail, sh_string_str(list->recipient),
732                         sh_nmail_valid_message_for_alias, list, S_TRUE);
733
734        if (msg)
735          {
736            if (!smsg) /* init */
737              {
738                smsg = sh_string_copy(msg);
739              }
740            else
741              {
742                if (0 != strcmp(sh_string_str(smsg), sh_string_str(msg)))
743                  {
744                    /*
745                     * Don't set list = list->next here, since we want
746                     * to continue with this recipient in the next batch.
747                     */
748                    sh_string_destroy(&msg);
749                    break;
750                  }
751              }
752            list->send_mail = 1;
753            sh_string_destroy(&msg);
754          }
755        list = list->next;
756      }
757
758    /* Continue here if smsg != msg */
759
760    if (smsg)
761      {
762        SH_MUTEX_LOCK(mutex_flush_l);
763        (void) sh_mail_msg(sh_string_str(smsg));
764        SH_MUTEX_UNLOCK(mutex_flush_l);
765        sh_string_destroy(&smsg);
766      }
767
768    /* Reset old list of recipients (up to current point in list)
769     * and then continue with list from current point on.
770     */
771    dlist  = recipient_list;
772    while (dlist)
773      {
774        dlist->send_mail = 0;
775        dlist = dlist->next;
776      }
777  }
778
779  /* Remove all mails for which no recipient failed
780   */
781
782  sh.mailNum.alarm_last -= commit_list(fifo_mail);
783  SH_MUTEX_UNLOCK(mutex_listall);
784
785  return retval;
786}
787
788
789
790/* <<<<<<<<<<<<<<<<<<<  Severity  >>>>>>>>>>>>>>>>>>>>>> */
791
792/*
793 * -- set severity threshold for recipient or alias
794 */
795int sh_nmail_set_severity (const char * str)
796{
797  if (last == recipient_list || last == alias_list)
798    {
799      if (0 == sh_error_set_level(str, &(last->severity)))
800        {
801          /* All recipients in alias share the severity
802           */
803          if (last == alias_list)
804            {
805              struct alias * ptr = last->recipient_list;
806
807              while (ptr)
808                {
809                  ptr->severity = last->severity;
810                  ptr = ptr->next;
811                }
812            }
813          return 0;
814        }
815    }
816  return (-1);
817}
818
819/* <<<<<<<<<<<<<<<<<<<  Filters >>>>>>>>>>>>>>>>>>>>>> */
820
821
822int sh_nmail_add_generic (const char * str, int flag)
823{
824  if (last)
825    {
826      if (NULL == last->mail_filter)
827        last->mail_filter = sh_filter_alloc();
828
829      /* All recipients in alias share the mail filter
830       */
831      if (last == alias_list)
832        {
833          struct alias * ptr = last->recipient_list;
834         
835          while (ptr)
836            {
837              ptr->mail_filter = last->mail_filter;
838              ptr = ptr->next;
839            }
840        }
841
842      return (sh_filter_add (str, last->mail_filter, flag));
843    }
844  return (-1);
845}
846
847/*
848 * -- add keywords to the OR filter
849 */
850int sh_nmail_add_or (const char * str)
851{
852  return sh_nmail_add_generic(str, SH_FILT_OR);
853}
854
855/*
856 * -- add keywords to the AND filter
857 */
858int sh_nmail_add_and (const char * str)
859{
860  return sh_nmail_add_generic(str, SH_FILT_AND);
861}
862
863/*
864 * -- add keywords to the NOT filter
865 */
866int sh_nmail_add_not (const char * str)
867{
868  return sh_nmail_add_generic(str, SH_FILT_NOT);
869}
870
871
872/* <<<<<<<<<<<<<<<<<<<  Mailkey per Alias >>>>>>>>>>>>>>>>>>>>>>>>> */
873
874#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
875#include <sys/mman.h>
876#endif
877
878#include "zAVLTree.h"
879
880zAVLTree        * mailkeys = NULL;
881
882struct alias_mailkey {
883  char * alias;
884  unsigned int mailcount;
885  time_t       id_audit;
886  char   mailkey_old[KEY_LEN+1];
887  char   mailkey_new[KEY_LEN+1];
888};
889
890static zAVLKey sh_nmail_getkey(void const *item)
891{
892  const struct alias_mailkey * t = (const struct alias_mailkey *) item;
893  return (zAVLKey) t->alias;
894}
895
896/* Return mailkey for alias. If there's no key yet, create it and
897 * store it in the AVL tree.
898 * This is called from sh_mail_msg,
899 *    which is called from sh_nmail_msg,
900 *        which is protected by a mutex.
901 */
902int sh_nmail_get_mailkey (const char * alias, char * buf, size_t bufsiz,
903                          time_t * id_audit)
904{
905  char hashbuf[KEYBUF_SIZE];
906
907 start:
908
909  if (mailkeys)
910    {
911      struct alias_mailkey * t;
912
913      if (!alias)
914        t = (struct alias_mailkey *) zAVLSearch (mailkeys, _("(null)"));
915      else
916        t = (struct alias_mailkey *) zAVLSearch (mailkeys, alias);
917
918      if (t)
919        {
920          /* iterate the key
921           */
922          (void) sl_strlcpy(t->mailkey_new,
923                            sh_tiger_hash (t->mailkey_old, TIGER_DATA, KEY_LEN,
924                                           hashbuf, sizeof(hashbuf)),
925                            KEY_LEN+1);
926          (void) sl_strlcpy(buf, t->mailkey_new, bufsiz);
927          ++(t->mailcount);
928        }
929      else
930        {
931          t = SH_ALLOC(sizeof(struct alias_mailkey));
932
933          MLOCK(t, sizeof(struct alias_mailkey));
934
935          if (!alias)
936            t->alias = sh_util_strdup(_("(null)"));
937          else
938            t->alias = sh_util_strdup(alias);
939
940          t->mailcount = 0;
941          t->id_audit  = time(NULL);
942
943          BREAKEXIT(sh_util_keyinit);
944          (void) sh_util_keyinit (t->mailkey_old, KEY_LEN+1);
945
946          /* iterate the key
947           */
948          (void) sl_strlcpy(t->mailkey_new,
949                            sh_tiger_hash (t->mailkey_old, TIGER_DATA, KEY_LEN,
950                                           hashbuf, sizeof(hashbuf)),
951                            KEY_LEN+1);
952          (void) sl_strlcpy(buf, t->mailkey_new, bufsiz);
953          (void) zAVLInsert(mailkeys, t);
954        }
955
956      /* X(n) -> X(n-1)
957       */
958      (void) sl_strlcpy (t->mailkey_old, t->mailkey_new, KEY_LEN+1);
959
960      *id_audit = t->id_audit;
961
962      return (t->mailcount);
963    }
964
965  mailkeys = zAVLAllocTree (sh_nmail_getkey, zAVL_KEY_STRING);
966  goto start;
967}
968
969/* <<<<<<<<<<<<<<<<<<<  Free for Reconfigure >>>>>>>>>>>>>>>>>>>>>> */
970
971
972static void free_recipient_list(struct alias * list)
973{
974  struct alias * new;
975  sh_filter_type * p = NULL;
976
977  while (list)
978    {
979      new  = list;
980      list = new->next;
981      if (new->mx_list)
982        free_mx(new->mx_list);
983      if (new->mail_filter)
984        {
985          sh_filter_free(new->mail_filter);
986          if (!p || p != new->mail_filter)
987            {
988              p = new->mail_filter;
989              SH_FREE(new->mail_filter);
990            }
991        }
992      sh_string_destroy(&(new->recipient));
993      SH_FREE(new);
994    }
995}
996
997/* Free everything to prepare for reconfigure
998 */
999void sh_nmail_free()
1000{
1001  SH_MUTEX_LOCK_UNSAFE(mutex_listall);
1002  all_recipients = NULL;
1003  SH_MUTEX_UNLOCK_UNSAFE(mutex_listall);
1004
1005  free_recipient_list(recipient_list);
1006  recipient_list = NULL;
1007
1008  sh_filter_free(&compiled_mail_filter);
1009
1010  while (alias_list) 
1011    {
1012      struct alias * item = alias_list;
1013
1014      alias_list = item->next;
1015
1016      sh_string_destroy(&(item->recipient));
1017      free_recipient_list(item->recipient_list);
1018      if (item->mail_filter)
1019        {
1020          sh_filter_free(item->mail_filter);
1021          /* SH_FREE(item->mail_filter); */
1022        }
1023      SH_FREE(item);
1024    }
1025  alias_list = NULL;
1026
1027  last = compiled_recipient_list;
1028  return;
1029}
1030
1031/* defined(SH_WITH_MAIL) */
1032#endif
Note: See TracBrowser for help on using the repository browser.