source: trunk/src/sh_nmail.c@ 500

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

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

File size: 22.3 KB
RevLine 
[232]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
[474]26#if defined(GCC_VERSION_MAJOR) && !defined(__clang__)
[465]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
[232]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);
[240]52SH_MUTEX_INIT(mutex_flush_l, PTHREAD_MUTEX_INITIALIZER);
[232]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
[272]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)
[232]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;
[272]86 if (isAll)
87 item = item->all_next;
88 else
89 item = item->next;
[232]90 }
91 }
92 return 0;
93}
94
[272]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 */
[232]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;
[272]111 new->isAlias = 0;
[232]112 new->recipient = sh_string_new_from_lchar(str, strlen(str));
113 list = new;
114
115 SH_MUTEX_LOCK_UNSAFE(mutex_listall);
[275]116 if (0 != check_double(str, all_recipients, S_TRUE))
[272]117 {
118 new->isAlias = 1;
119 }
[232]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
[272]139/* Add a single recipient. Must not be in in
140 * recipient_list already, and not in all_recipients.
[232]141 */
142int sh_nmail_add_recipient(const char * str)
143{
[272]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))
[232]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{
[272]161 if (0 == check_double(str, compiled_recipient_list, S_FALSE))
[232]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 {
[272]192 /* strip trailing space
193 */
[232]194 --q; while ((q != new) && *q == ' ') { *q = '\0'; --q; }
195 }
196 else
197 {
198 goto err;
199 }
200
[272]201 if (0 == check_double(new, alias_list, S_FALSE))
[232]202 {
203 array = split_array_list(p, &nfields, lengths);
204
205 if (array && nfields > 0)
206 {
[272]207 struct alias * newalias = NULL;
[232]208
[272]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))
[275]215 nflag = 1; /* not in all_recipients --> bad */
[272]216 }
217
218 if (nflag == 0)
[232]219 {
[272]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)
[232]230 {
[272]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 }
[232]237 }
238 }
239
240 SH_FREE(array);
241
[304]242 if (newalias == NULL || newalias->recipient_list == NULL)
[232]243 {
[304]244 if (newalias)
245 SH_FREE(newalias);
[232]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{
[481]331 const struct alias * rcv = (const struct alias *) rcv_info;
[232]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)
[272]411 {
412 /* Don't mark aliases
413 */
414 if (flagit && list->isAlias == 0)
[275]415 {
416 list->send_mail = 1;
417 }
[272]418 list = list->all_next;
419 }
[232]420 else
[272]421 {
422 if (flagit)
423 list->send_mail = 1;
424 list = list->next;
425 }
[232]426 ++retval;
427 }
428 }
429 return retval;
430}
431
[240]432/* Is not called from same(recursively) or different thread
433 */
[232]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
[240]449/* Can be called from same thread with mutex_listall held via sh_nmail_flush()
450 */
[232]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 {
[240]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 }
[232]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
[240]490static int nmail_count = 0;
491
[232]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 {
[240]510 ++nmail_count;
511 if (nmail_count != 1)
[232]512 {
[240]513 --nmail_count;
[232]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 {
[275]529 sh_error_handle (SH_ERR_ALL, FIL__, __LINE__,
530 retval, MSG_E_SUBGEN,
531 _("could not mail immediately"),
532 _("sh_nmail_msg") );
[232]533 sh_mail_pushstack(level, message, alias);
534 }
535 }
536 SH_MUTEX_LOCK_UNSAFE(nmail_lock);
[240]537 --nmail_count;
[232]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
[240]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
[232]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
[240]581static int sh_nmail_flush_int ()
[232]582{
583 int retval = 0;
584 sh_string * msg = NULL;
585 sh_string * smsg = NULL;
586 struct alias * list;
587 struct alias * dlist;
588
[240]589 /* warning: variable ‘list’ might be clobbered by ‘longjmp’ or ‘vfork’*/
590 list_dummy = &list;
591
[232]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
[272]610 /* Compiled recipients. These share threshold and filter,
611 * hence only the first recipient needs to be tested.
[232]612 */
613 list = compiled_recipient_list;
614
615 if (list)
616 {
617 msg = tag_list(fifo_mail, sh_string_str(list->recipient),
[272]618 sh_nmail_valid_message_for_alias, list, S_TRUE);
[232]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
[240]631 SH_MUTEX_LOCK(mutex_flush_l);
[232]632 (void) sh_mail_msg(sh_string_str(msg));
[240]633 SH_MUTEX_UNLOCK(mutex_flush_l);
634
[232]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),
[272]660 sh_nmail_valid_message_for_alias, list, S_FALSE);
[232]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 {
[240]695 SH_MUTEX_LOCK(mutex_flush_l);
[232]696 (void) sh_mail_msg(sh_string_str(smsg));
[240]697 SH_MUTEX_UNLOCK(mutex_flush_l);
[232]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),
[272]732 sh_nmail_valid_message_for_alias, list, S_TRUE);
[232]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 {
[240]762 SH_MUTEX_LOCK(mutex_flush_l);
[232]763 (void) sh_mail_msg(sh_string_str(smsg));
[240]764 SH_MUTEX_UNLOCK(mutex_flush_l);
[232]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
[363]965 mailkeys = zAVLAllocTree (sh_nmail_getkey, zAVL_KEY_STRING);
[232]966 goto start;
967}
968
969/* <<<<<<<<<<<<<<<<<<< Free for Reconfigure >>>>>>>>>>>>>>>>>>>>>> */
970
971
972static void free_recipient_list(struct alias * list)
973{
974 struct alias * new;
[276]975 sh_filter_type * p = NULL;
[232]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);
[276]986 if (!p || p != new->mail_filter)
987 {
988 p = new->mail_filter;
989 SH_FREE(new->mail_filter);
990 }
[232]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);
[276]1021 /* SH_FREE(item->mail_filter); */
[232]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.