1 /* SAMHAIN file system integrity testing                                   */
2 /* Copyright (C) 1999, 2000 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 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <ctype.h>
26 
27 #undef  FIL__
28 #define FIL__  _("sh.fifo.c")
29 
30 
31 #include "samhain.h"
32 #include "sh_mem.h"
33 #include "sh_unix.h"
34 #include "sh_utils.h"
35 #include "sh_string.h"
36 #include "sh_fifo.h"
37 
38 #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
39 #include <sys/mman.h>
40 #endif
41 
42 #define SH_FIFO_TAGGED 1
43 #define SH_FIFO_M_FAIL 2
44 #define SH_FIFO_MARKED 4
45 
46 /* Prepare an email message and return it. Iterate over list on stack and
47  * check for each if it is valid for recipient 'tag'. If yes, add to the
48  * returned string.
49  * okNull == False means that item->s_xtra must be defined
50  */
tag_list(SH_FIFO * fifo,char * tag,int (* valid)(int,const char *,const char *,const void *),const void * info,int okNull)51 sh_string * tag_list (SH_FIFO * fifo, char * tag,
52 		      int(*valid)(int, const char*, const char*, const void*),
53 		      const void * info, int okNull)
54 {
55   struct dlist * item;
56   sh_string * result = NULL;
57 
58   if (fifo && fifo->fifo_cts > 0)
59     {
60       item = fifo->head_ptr;
61 
62       while (item)
63 	{
64 	  /* Same recipient, or no recipient ( := all )
65 	   */
66 	  if ( (tag && item->s_xtra && 0 == strcmp(item->s_xtra, tag)) ||
67 	       ((okNull == S_TRUE) && !(item->s_xtra)) )
68 	    {
69 	      if (valid == NULL)
70 		{
71 		  item->transact |= SH_FIFO_TAGGED;
72 		}
73 	      else
74 		{
75 		  /* level, message, recipient, list */
76 		  if (!valid(item->i_xtra, item->data, tag, info))
77 		    goto skipped;
78 		  item->transact |= SH_FIFO_TAGGED;
79 		}
80 	      if (!result)
81 		{
82 		  result = sh_string_new_from_lchar(item->data, strlen(item->data));
83 		}
84 	      else
85 		{
86 		  result = sh_string_cat_lchar(result, "\r\n", 2);
87 		  result = sh_string_add_from_char(result, item->data);
88 		}
89 	    }
90 	skipped:
91 	  item = item->next;
92 	}
93     }
94   return result;
95 }
96 
rollback_list(SH_FIFO * fifo)97 void rollback_list (SH_FIFO * fifo)
98 {
99   struct dlist * item;
100 
101   if (fifo && fifo->fifo_cts > 0)
102     {
103       item = fifo->head_ptr;
104 
105       while (item && 0 != (item->transact & SH_FIFO_TAGGED))
106 	{
107 	  item->transact |= SH_FIFO_M_FAIL;
108 	  item = item->next;
109 	}
110     }
111 }
112 
mark_list(SH_FIFO * fifo)113 void mark_list (SH_FIFO * fifo)
114 {
115   struct dlist * item;
116 
117   if (fifo && fifo->fifo_cts > 0)
118     {
119       item = fifo->head_ptr;
120 
121       while (item && 0 != (item->transact & SH_FIFO_TAGGED))
122 	{
123 	  item->transact |= SH_FIFO_MARKED;
124 	  item = item->next;
125 	}
126     }
127 }
128 
reset_list(SH_FIFO * fifo)129 void reset_list (SH_FIFO * fifo)
130 {
131   struct dlist * item;
132 
133   if (fifo && fifo->fifo_cts > 0)
134     {
135       item = fifo->head_ptr;
136 
137       while (item)
138 	{
139 	  item->transact = 0;
140 	  item = item->next;
141 	}
142     }
143 }
144 
commit_list(SH_FIFO * fifo)145 int commit_list (SH_FIFO * fifo)
146 {
147   struct dlist * item;
148   struct dlist * getit;
149   int    retval = 0;
150 
151   if (fifo && fifo->fifo_cts > 0)
152     {
153       item = fifo->head_ptr;
154 
155       while (item)
156 	{
157 	  getit = NULL;
158 
159 	  if ( 0 != (item->transact & SH_FIFO_MARKED) && /* sent              */
160 	       0 == (item->transact & SH_FIFO_M_FAIL) )  /* no recipient fail */
161 	    {
162 	      if (item == fifo->head_ptr)
163 		fifo->head_ptr   = item->next;
164 	      if (item == fifo->tail_ptr)
165 		fifo->tail_ptr   = item->prev;
166 	      if (item->prev)
167 		item->prev->next = item->next;
168 	      if (item->next)
169 		item->next->prev = item->prev;
170 	      --(fifo->fifo_cts);
171 	      getit = item;
172 	    }
173 	  item  = item->next;
174 
175 	  /* Delete it
176 	   */
177 	  if (getit)
178 	    {
179 	      size_t len = sl_strlen(getit->data);
180 	      memset(getit->data, 0, len);
181 	      if (NULL != sl_strstr (getit->data, _("LOGKEY")))
182 		MUNLOCK(getit->data, (len+1));
183 	      if (getit->s_xtra)
184 		SH_FREE(getit->s_xtra);
185 	      SH_FREE(getit->data);
186 	      SH_FREE(getit);
187 	      ++retval;
188 	    }
189 	}
190     }
191   return retval;
192 }
193 
194 /* push an item on the head of the list
195  */
push_list(SH_FIFO * fifo,const char * indat,int in_i,const char * in_str)196 int push_list (SH_FIFO * fifo, const char * indat, int in_i, const char * in_str)
197 {
198   struct dlist * item;
199   size_t         len;
200 
201   SL_ENTER(_("push_list"));
202 
203   if (indat == NULL || fifo == NULL)
204     {
205       SL_RETURN((-1), _("push_list"));
206     }
207 
208   if (fifo->fifo_cts > SH_FIFO_MAX)
209     {
210       SL_RETURN((-1), _("push_list"));
211     }
212 
213   len             = sl_strlen(indat);
214 
215   if (len == 0)
216     {
217       SL_RETURN((-1), _("push_list"));
218     }
219   item            = SH_ALLOC(sizeof(struct dlist));
220   item->data      = SH_ALLOC(len+1);
221 
222   if (NULL != sl_strstr (indat, _("LOGKEY")))
223     MLOCK(item->data, (len+1));
224 
225   sl_strlcpy (item->data, indat, len+1);
226   item->data[len] = '\0';
227 
228   item->i_xtra = in_i;
229   if (in_str)
230     item->s_xtra = sh_util_strdup(in_str);
231   else
232     item->s_xtra = NULL;
233   item->transact = 0;
234 
235   if (fifo->tail_ptr == NULL)
236     {
237       fifo->tail_ptr = item;
238       item->prev     = NULL;
239     }
240   else
241     {
242       fifo->head_ptr->prev = item;
243       item->prev           = NULL;
244     }
245 
246   item->next      = fifo->head_ptr;
247   fifo->head_ptr  = item;
248 
249   ++(fifo->fifo_cts);
250 
251   SL_RETURN((fifo->fifo_cts), _("push_list"));
252 }
253 
254 /* push an item on the tail of the list
255  */
push_tail_list(SH_FIFO * fifo,const char * indat,int in_i,const char * in_str)256 int push_tail_list (SH_FIFO * fifo, const char * indat, int in_i, const char * in_str)
257 {
258   struct dlist * item;
259   size_t         len;
260 
261   SL_ENTER(_("push_tail_list"));
262 
263   if (indat == NULL || fifo == NULL)
264     {
265       SL_RETURN((-1), _("push_tail_list"));
266     }
267 
268   if (fifo->fifo_cts > SH_FIFO_MAX)
269     {
270       SL_RETURN((-1), _("push_tail_list"));
271     }
272 
273   len = sl_strlen(indat);
274   if (len == 0)
275     {
276       SL_RETURN((-1), _("push_list"));
277     }
278 
279   item            = SH_ALLOC(sizeof(struct dlist));
280   item->data      = SH_ALLOC(len+1);
281 
282   if (NULL != sl_strstr (indat, _("LOGKEY")))
283     MLOCK(item->data, (len+1));
284 
285   sl_strlcpy (item->data, indat, len+1);
286   item->data[len] = '\0';
287 
288   item->i_xtra = in_i;
289   if (in_str)
290     item->s_xtra = sh_util_strdup(in_str);
291   else
292     item->s_xtra = NULL;
293   item->transact = 0;
294 
295   if (fifo->head_ptr == NULL)
296     {
297       item->next     = NULL;
298       fifo->head_ptr = item;
299     }
300   else
301     {
302       item->next           = NULL;
303       fifo->tail_ptr->next = item;
304     }
305 
306   item->prev     = fifo->tail_ptr;
307   fifo->tail_ptr = item;
308 
309   ++(fifo->fifo_cts);
310 
311   SL_RETURN((fifo->fifo_cts), _("push_tail_list"));
312 }
313 
314 /* pop an item from the tail of the list
315  */
pop_list(SH_FIFO * fifo)316 /*@null@*/ char * pop_list (SH_FIFO * fifo)
317 {
318   size_t         len;
319   struct dlist * getit;
320   char         * retval;
321 
322   SL_ENTER(_("pop_list"));
323 
324   if (fifo == NULL || fifo->tail_ptr == NULL)
325     {
326       SL_RETURN (NULL, _("pop_list"));
327     }
328 
329   getit       = fifo->tail_ptr;
330 
331   if (getit->prev == NULL) /* last element */
332     {
333       fifo->tail_ptr = NULL;
334       fifo->head_ptr = NULL;
335     }
336   else
337     {
338       fifo->tail_ptr        = getit->prev;
339       fifo->tail_ptr->next  = getit->next;
340     }
341 
342   len         = sl_strlen(getit->data);
343   retval      = SH_ALLOC(len+1);
344   sl_strlcpy (retval, getit->data, len+1);
345 
346   memset(getit->data, 0, len);
347 
348   if (NULL != sl_strstr (retval, _("LOGKEY")))
349     MUNLOCK(getit->data, (len+1));
350 
351   if (getit->s_xtra)
352     SH_FREE(getit->s_xtra);
353   SH_FREE(getit->data);
354   SH_FREE(getit);
355 
356   --(fifo->fifo_cts);
357 
358   SL_RETURN (retval, _("pop_list"));
359 }
360 
361 
362 #ifdef SH_CUTEST
363 #include "CuTest.h"
364 
Test_fifo(CuTest * tc)365 void Test_fifo (CuTest *tc) {
366 
367   SH_FIFO ff;
368   int ret;
369   char * p;
370 
371   fifo_init(&ff);
372 
373   p = sh_fifo_pop(&ff);
374   CuAssertPtrEquals(tc, NULL, p);
375 
376   /* first sequence */
377   ret = sh_fifo_push(&ff, "one");
378   CuAssertIntEquals(tc,1,ret);
379   ret = sh_fifo_push(&ff, "two");
380   CuAssertIntEquals(tc,2,ret);
381   ret = sh_fifo_push(&ff, "three");
382   CuAssertIntEquals(tc,3,ret);
383 
384   p = sh_fifo_pop(&ff);
385   CuAssertPtrNotNull(tc, p);
386   CuAssertStrEquals(tc,"one", p);
387   p = sh_fifo_pop(&ff);
388   CuAssertPtrNotNull(tc, p);
389   CuAssertStrEquals(tc,"two", p);
390   p = sh_fifo_pop(&ff);
391   CuAssertPtrNotNull(tc, p);
392   CuAssertStrEquals(tc,"three", p);
393   p = sh_fifo_pop(&ff);
394   CuAssertPtrEquals(tc, NULL, p);
395 
396   /* second sequence */
397   ret = sh_fifo_push(&ff, "one");
398   CuAssertIntEquals(tc,1,ret);
399   p = sh_fifo_pop(&ff);
400   CuAssertPtrNotNull(tc, p);
401   CuAssertStrEquals(tc,"one", p);
402   ret = sh_fifo_push_tail(&ff, "one");
403   CuAssertIntEquals(tc,1,ret);
404   p = sh_fifo_pop(&ff);
405   CuAssertPtrNotNull(tc, p);
406   CuAssertStrEquals(tc,"one", p);
407   p = sh_fifo_pop(&ff);
408   CuAssertPtrEquals(tc, NULL, p);
409 
410   /* third sequence */
411   ret = sh_fifo_push(&ff, "one");
412   CuAssertIntEquals(tc,1,ret);
413   ret = sh_fifo_push(&ff, "two");
414   CuAssertIntEquals(tc,2,ret);
415   ret = sh_fifo_push(&ff, "three");
416   CuAssertIntEquals(tc,3,ret);
417 
418   p = sh_fifo_pop(&ff);
419   CuAssertPtrNotNull(tc, p);
420   CuAssertStrEquals(tc,"one", p);
421   ret = sh_fifo_push_tail(&ff, p);
422   CuAssertIntEquals(tc,3,ret);
423 
424   p = sh_fifo_pop(&ff);
425   CuAssertPtrNotNull(tc, p);
426   CuAssertStrEquals(tc,"one", p);
427   p = sh_fifo_pop(&ff);
428   CuAssertPtrNotNull(tc, p);
429   CuAssertStrEquals(tc,"two", p);
430   p = sh_fifo_pop(&ff);
431   CuAssertPtrNotNull(tc, p);
432   CuAssertStrEquals(tc,"three", p);
433   p = sh_fifo_pop(&ff);
434   CuAssertPtrEquals(tc, NULL, p);
435 }
436 
437 #endif
438 
439 
440 
441 
442