source: trunk/src/sh_files.c@ 481

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

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

File size: 81.1 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999 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#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <ctype.h>
30#include <limits.h>
31
32#include <errno.h>
33
34/* Must be before <utime.h> on FreeBSD
35 */
36#include <sys/types.h>
37#include <unistd.h>
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41
42#if !defined(O_NOATIME)
43#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__PPC__))
44#define O_NOATIME 01000000
45#endif
46#endif
47
48#include <utime.h>
49
50#ifdef HAVE_DIRENT_H
51#include <dirent.h>
52#define NAMLEN(dirent) sl_strlen((dirent)->d_name)
53#else
54#define dirent direct
55#define NAMLEN(dirent) (dirent)->d_namlen
56#ifdef HAVE_SYS_NDIR_H
57#include <sys/ndir.h>
58#endif
59#ifdef HAVE_SYS_DIR_H
60#include <sys/dir.h>
61#endif
62#ifdef HAVE_NDIR_H
63#include <ndir.h>
64#endif
65#endif
66#define NEED_ADD_DIRENT
67
68#ifdef HAVE_GLOB_H
69#include <glob.h>
70#endif
71#ifdef HAVE_FNMATCH_H
72#include <fnmatch.h>
73#endif
74
75
76#include "samhain.h"
77
78#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
79
80#include "sh_pthread.h"
81#include "sh_error.h"
82#include "sh_utils.h"
83#include "sh_unix.h"
84#include "sh_files.h"
85#include "sh_tiger.h"
86#include "sh_hash.h"
87#include "sh_ignore.h"
88#include "sh_inotify.h"
89#include "zAVLTree.h"
90#include "sh_dbIO.h"
91
92#undef FIL__
93#define FIL__ _("sh_files.c")
94
95extern sh_watches sh_file_watches;
96
97static char * sh_files_C_dequote (char * s, size_t * length)
98{
99 size_t i, len = *length;
100 int flag = 0;
101 char *p, *q, *po, *pend;
102
103 /* search for backslash
104 */
105 for (i = 0; i < len; ++i)
106 {
107 if (s[i] == '\\')
108 {
109 flag = 1;
110 break;
111 }
112 }
113
114 if (flag == 0 || *s == '\0')
115 return s;
116
117 po = SH_ALLOC(len+1); *po = '\0'; p = po; pend = &po[len];
118
119 q = s;
120
121 do
122 {
123 if (*q == '\\')
124 {
125 ++q;
126
127 if (*q == '\0')
128 { *p = *q; flag = 0; break; }
129 else if (*q == 'a')
130 { *p = '\a'; ++p; ++q; }
131 else if (*q == 'b')
132 { *p = '\b'; ++p; ++q; }
133 else if (*q == 'f')
134 { *p = '\f'; ++p; ++q; }
135 else if (*q == 'n')
136 { *p = '\n'; ++p; ++q; }
137 else if (*q == 'r')
138 { *p = '\r'; ++p; ++q; }
139 else if (*q == 't')
140 { *p = '\t'; ++p; ++q; }
141 else if (*q == 'v')
142 { *p = '\v'; ++p; ++q; }
143 else if (*q == '\\')
144 { *p = '\\'; ++p; ++q; }
145 else if (*q == '\'')
146 { *p = '\''; ++p; ++q; }
147 else if (*q == '"')
148 { *p = '"'; ++p; ++q; }
149 else if (*q == 'x')
150 {
151 if (isxdigit((int) q[1]) && isxdigit((int) q[2]))
152 {
153 /* hexadecimal value following */
154 unsigned char cc = (16 * sh_util_hexchar(q[1]))
155 + sh_util_hexchar(q[2]);
156 *p = (char) cc;
157 ++p; q += 3;
158 }
159 else
160 {
161 *p = '\0'; flag = 0; break;
162 }
163 }
164 else if (isdigit((int)*q))
165 {
166 if (isdigit((int) q[1]) && q[1] < '8' &&
167 isdigit((int) q[2]) && q[2] < '8')
168 {
169 /* octal value following */
170 char tmp[4]; unsigned char cc;
171 tmp[0] = *q; ++q; tmp[1] = *q; ++q; tmp[2] = *q; ++q;
172 tmp[3] = '\0';
173 cc = strtol(tmp, NULL, 8);
174 *p = (char) cc; ++p;
175 }
176 else
177 {
178 *p = '\0'; flag = 0; break;
179 }
180 }
181 else
182 {
183 /* invalid escape sequence */
184 *p = '\0'; flag = 0; break;
185 }
186 }
187 else
188 {
189 *p = *q;
190 ++p; ++q;
191 }
192 } while (*q && p <= pend);
193
194 SL_REQUIRE (p <= pend, _("p <= pend"));
195
196 if (flag)
197 {
198 *p = '\0';
199 *length = strlen(po);
200 }
201 else
202 {
203 SH_FREE(po);
204 po = NULL;
205 *length = 0;
206 }
207
208 SL_REQUIRE (*length <= len, _("*length <= len"));
209
210 SH_FREE(s);
211 return po;
212}
213
214char * sh_files_parse_input(const char * str_s, size_t * len)
215{
216 char * p;
217
218 if (!str_s || *str_s == '\0')
219 return NULL;
220
221 *len = sl_strlen(str_s);
222
223 if ( (str_s[0] == '"' && str_s[*len-1] == '"' ) ||
224 (str_s[0] == '\'' && str_s[*len-1] == '\'') )
225 {
226 if (*len < 3)
227 return NULL;
228 --(*len);
229 p = sh_util_strdup_l(&str_s[1], *len);
230 p[*len-1] = '\0';
231 --(*len);
232 }
233 else
234 {
235 p = sh_util_strdup_l(str_s, *len);
236 }
237
238 p = sh_files_C_dequote(p, len);
239
240 return p;
241}
242
243
244extern int flag_err_debug;
245extern int flag_err_info;
246
247int sh_files_reportonce(const char * c)
248{
249 int i;
250 SL_ENTER(_("sh_files_reportonce"));
251 i = sh_util_flagval(c, &(sh.flag.reportonce));
252
253 SL_RETURN(i, _("sh_files_reportonce"));
254}
255
256int sh_files_fulldetail(const char * c)
257{
258 int i;
259 SL_ENTER(_("sh_files_fulldetail"));
260 i = sh_util_flagval(c, &(sh.flag.fulldetail));
261
262 SL_RETURN((i), _("sh_files_fulldetail"));
263}
264
265
266typedef struct dir_struct {
267 long NumRegular;
268 long NumDirs;
269 long NumSymlinks;
270 long NumFifos;
271 long NumSockets;
272 long NumCDev;
273 long NumBDev;
274 long NumDoor;
275 long NumPort;
276 long NumAll;
277 long TotalBytes;
278 char DirPath[PATH_MAX];
279} dir_type;
280
281typedef struct dirstack_entry {
282 char * name;
283 int class;
284 unsigned long check_flags;
285 int rdepth;
286 short checked;
287 short childs_checked;
288 short is_reported;
289 /* struct dirstack_entry * next; */
290} dirstack_t;
291
292
293/* the destructor
294 */
295void free_dirstack (void * inptr)
296{
297 dirstack_t * here;
298
299 SL_ENTER(_("free_dirstack"));
300 if (inptr == NULL)
301 SL_RET0(_("free_dirstack"));
302 else
303 here = (dirstack_t *) inptr;
304
305 if (here->name != NULL)
306 SH_FREE(here->name);
307 SH_FREE(here);
308 SL_RET0(_("free_dirstack"));
309}
310
311/* Function to return the key for indexing
312 * the argument
313 */
314zAVLKey zdirstack_key (void const * arg)
315{
316 const dirstack_t * sa = (const dirstack_t *) arg;
317 return (zAVLKey) sa->name;
318}
319
320#define SH_LIST_FILE 0
321#define SH_LIST_DIR1 1
322#define SH_LIST_DIR2 2
323
324
325static int which_dirList = SH_LIST_DIR1;
326
327static zAVLTree * zdirListOne = NULL;
328static zAVLTree * zdirListTwo = NULL;
329static zAVLTree * zfileList = NULL;
330
331SH_MUTEX_STATIC(mutex_zfiles, PTHREAD_MUTEX_INITIALIZER);
332SH_MUTEX_STATIC(mutex_zglob, PTHREAD_MUTEX_INITIALIZER);
333SH_MUTEX_RECURSIVE(mutex_zdirs);
334
335static int sh_files_fullpath (const char * testdir,
336 const char * d_name,
337 char * statpath);
338static int sh_files_pushdir (int class, const char * str_s);
339static int sh_files_pushfile (int class, const char * str_s);
340
341static long MaxRecursionLevel = 0;
342
343/* set default recursion level
344 */
345int sh_files_setrecursion (const char * flag_s)
346{
347 long flag = 0;
348 static int reject = 0;
349
350 SL_ENTER( _("sh_files_setrecursion"));
351
352 if (reject == 1)
353 SL_RETURN((-1), _("sh_files_setrecursion"));
354
355 if (sh.flag.opts == S_TRUE)
356 reject = 1;
357
358 if (flag_s != NULL)
359 flag = (int)(atof(flag_s));
360
361 if (flag >= 0 && flag <= 99)
362 MaxRecursionLevel = flag;
363 else
364 SL_RETURN((-1), _("sh_files_setrecursion"));
365
366 SL_RETURN((0), _("sh_files_setrecursion"));
367}
368
369static int handle_filecheck_ret(dirstack_t * ptr, char * tmp_in, int status)
370{
371 int fcount = 0;
372 char * tmp;
373
374 if (!tmp_in)
375 tmp = sh_util_safe_name (ptr->name);
376 else
377 tmp = tmp_in;
378
379 if (status == SH_FILE_UNKNOWN && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
380 {
381 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
382 tmp, status));
383
384 if ( sh.flag.checkSum == SH_CHECK_INIT ||
385 sh_hash_have_it (ptr->name) >= 0)
386 {
387 if (S_FALSE == sh_ignore_chk_del(ptr->name))
388 {
389 if (0 != hashreport_missing(ptr->name,
390 (ptr->class == SH_LEVEL_ALLIGNORE) ?
391 ShDFLevel[ptr->class] :
392 ShDFLevel[SH_ERR_T_FILE])) {
393 if (tmp == NULL)
394 tmp = sh_util_safe_name (ptr->name);
395 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
396 ShDFLevel[ptr->class] :
397 ShDFLevel[SH_ERR_T_FILE],
398 FIL__, __LINE__, 0, MSG_FI_MISS,
399 tmp);
400 ++sh.statistics.files_report;
401 }
402 }
403 }
404 else /* not there at init, and still missing */
405 {
406 if (tmp == NULL)
407 tmp = sh_util_safe_name (ptr->name);
408 sh_error_handle (SH_ERR_NOTICE,
409 FIL__, __LINE__, 0,
410 MSG_FI_FAIL,
411 tmp);
412 }
413
414 if (sh.flag.checkSum != SH_CHECK_INIT)
415 sh_hash_set_missing(ptr->name);
416
417 if (sh.flag.reportonce == S_TRUE)
418 SET_SH_FFLAG_REPORTED(ptr->is_reported);
419 }
420 else
421 {
422 /* exists (status >= 0), but was missing (reported == TRUE)
423 */
424 if (status != SH_FILE_UNKNOWN && SH_FFLAG_REPORTED_SET(ptr->is_reported))
425 {
426 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
427 sh_hash_clear_flag(ptr->name, SH_FFLAG_ENOENT);
428 }
429
430 /* Catchall
431 */
432 else if (status == SH_FILE_UNKNOWN)
433 {
434 /* Thu Mar 7 15:09:40 CET 2002 Make sure missing file
435 * is reported if ptr->reported == S_TRUE because the
436 * file has been added.
437 */
438 if (sh_hash_have_it (ptr->name) >= 0 &&
439 !SH_FFLAG_REPORTED_SET(ptr->is_reported))
440 {
441 if (S_FALSE == sh_ignore_chk_del(ptr->name))
442 {
443 if (0 != hashreport_missing(ptr->name,
444 (ptr->class == SH_LEVEL_ALLIGNORE) ?
445 ShDFLevel[ptr->class] :
446 ShDFLevel[SH_ERR_T_FILE])) {
447 if (tmp == NULL)
448 tmp = sh_util_safe_name (ptr->name);
449 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE)?
450 ShDFLevel[ptr->class] :
451 ShDFLevel[SH_ERR_T_FILE],
452 FIL__, __LINE__, 0, MSG_FI_MISS,
453 tmp);
454 ++sh.statistics.files_report;
455 }
456 }
457
458 /* delete from database
459 */
460 if (sh.flag.checkSum != SH_CHECK_INIT)
461 sh_hash_set_missing(ptr->name);
462 }
463 else
464 {
465 if (tmp == NULL)
466 tmp = sh_util_safe_name (ptr->name);
467 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
468 MSG_FI_FAIL,
469 tmp);
470 if (sh.flag.checkSum != SH_CHECK_INIT)
471 sh_hash_set_visited_true(ptr->name);
472 }
473 }
474
475 ++fcount;
476 }
477 if (!tmp_in)
478 SH_FREE(tmp);
479
480 return fcount;
481}
482
483
484unsigned long sh_files_chk ()
485{
486 zAVLCursor cursor;
487 ShFileType status;
488 unsigned long fcount = 0;
489
490 char * tmp = NULL;
491
492 dirstack_t * ptr;
493 char * dir;
494 char * file;
495 int tmp_reported;
496
497 SL_ENTER(_("sh_files_chk"));
498
499 for (ptr = (dirstack_t *) zAVLFirst(&cursor, zfileList); ptr;
500 ptr = (dirstack_t *) zAVLNext(&cursor))
501 {
502
503 if (sig_urgent > 0) {
504 SL_RETURN(fcount, _("sh_files_chk"));
505 }
506
507 if (ptr->checked == S_FALSE)
508 {
509 dir = sh_util_dirname (ptr->name);
510 file = sh_util_basename (ptr->name);
511#if defined(WITH_TPT)
512 tmp = sh_util_safe_name (ptr->name);
513#endif
514
515
516 if (flag_err_info == S_TRUE)
517 {
518 char pstr[32];
519#if !defined(WITH_TPT)
520 tmp = sh_util_safe_name (ptr->name);
521#endif
522 sl_strlcpy(pstr, sh_hash_getpolicy(ptr->class), sizeof(pstr));
523 sh_error_handle ((-1), FIL__, __LINE__, 0,
524 MSG_FI_CHK, pstr, tmp);
525 }
526
527 if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
528 {
529 sh_inotify_add_watch_later(ptr->name, &sh_file_watches, NULL,
530 ptr->class, ptr->check_flags,
531 SH_INOTIFY_FILE, 0);
532 }
533
534 BREAKEXIT(sh_files_filecheck);
535 tmp_reported = ptr->is_reported; /* fix aliasing warning */
536 status = sh_files_filecheck (ptr->class, ptr->check_flags, dir, file,
537 &tmp_reported, 0);
538 ptr->is_reported = tmp_reported;
539
540 TPT(( 0, FIL__, __LINE__,
541 _("msg=<filecheck complete: %s> status=<%d> reported=<%d>\n"),
542 tmp, status, ptr->is_reported));
543
544 fcount += handle_filecheck_ret(ptr, tmp, status);
545
546 if (tmp != NULL)
547 {
548 SH_FREE(tmp);
549 tmp = NULL;
550 }
551 if (file)
552 SH_FREE(file);
553 if (dir)
554 SH_FREE(dir);
555
556 ptr->checked = S_TRUE;
557 }
558 }
559
560 SL_RETURN(fcount, _("sh_files_chk"));
561}
562
563static zAVLTree * fileTree = NULL;
564static zAVLTree * dirTree = NULL;
565
566static void clear_lists()
567{
568 if (fileTree) {
569 zAVL_string_reset(fileTree);
570 fileTree = NULL;
571 }
572 if (dirTree) {
573 zAVL_string_reset(dirTree);
574 dirTree = NULL;
575 }
576 return;
577}
578
579static void add_to_filelist(zAVLTree * tree)
580{
581 dirstack_t * ptr;
582 zAVLCursor avlcursor;
583
584 SL_ENTER(_("add_to_filelist"));
585
586 SH_MUTEX_LOCK(mutex_zfiles);
587 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
588 ptr = (dirstack_t *) zAVLNext(&avlcursor))
589 zAVL_string_set (&fileTree, ptr->name);
590 SH_MUTEX_UNLOCK(mutex_zfiles);
591 SL_RET0(_("add_to_filelist"));
592}
593static void add_to_dirlist(zAVLTree * tree)
594{
595 dirstack_t * ptr;
596 zAVLCursor avlcursor;
597
598 SL_ENTER(_("add_to_dirlist"));
599
600 SH_MUTEX_LOCK(mutex_zfiles);
601 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
602 ptr = (dirstack_t *) zAVLNext(&avlcursor))
603 zAVL_string_set (&dirTree, ptr->name);
604 SH_MUTEX_UNLOCK(mutex_zfiles);
605 SL_RET0(_("add_to_dirlist"));
606}
607char * sh_files_findfile(const char * path)
608{
609 return zAVL_string_get (fileTree, path);
610}
611
612void * sh_dummy_621_candidate;
613
614static char * intern_find_morespecific_dir(zAVLTree * tree,
615 const char * path, size_t * len)
616{
617 dirstack_t * ptr;
618 zAVLCursor avlcursor;
619 size_t l_path = strlen(path);
620 size_t l_name;
621 char * candidate = NULL;
622 size_t l_candidate = 0;
623
624 if (NULL == tree)
625 return NULL;
626
627 sh_dummy_621_candidate = (void *) &candidate;
628
629 SH_MUTEX_LOCK(mutex_zfiles);
630 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
631 ptr = (dirstack_t *) zAVLNext(&avlcursor))
632 {
633 l_name = strlen(ptr->name);
634 if (l_name <= l_path)
635 {
636 if (0 == strncmp(ptr->name, path, l_name))
637 {
638 if ((l_name == l_path) || (path[l_name] == '/'))
639 {
640 if (!candidate || (l_candidate < l_name))
641 {
642 candidate = ptr->name;
643 l_candidate = l_name;
644 *len = l_candidate;
645 }
646 }
647 }
648 }
649 }
650 SH_MUTEX_UNLOCK(mutex_zfiles);
651 return candidate;
652}
653char * sh_files_find_mostspecific_dir(const char * path)
654{
655 size_t l_one = 0;
656 size_t l_two = 0;
657 char * one;
658 char * two;
659
660 one = intern_find_morespecific_dir(zdirListOne, path, &l_one);
661 two = intern_find_morespecific_dir(zdirListTwo, path, &l_two);
662
663 if (l_one > l_two) return one;
664 else return two;
665}
666
667int sh_files_delfilestack ()
668{
669 SL_ENTER(_("sh_files_delfilestack"));
670
671 SH_MUTEX_LOCK(mutex_zfiles);
672 zAVLFreeTree (zfileList, free_dirstack);
673 zfileList = NULL;
674 SH_MUTEX_UNLOCK(mutex_zfiles);
675
676 SL_RETURN(0, _("sh_files_delfilestack"));
677}
678
679int sh_files_setrec_int (zAVLTree * tree)
680{
681 dirstack_t * ptr;
682 zAVLCursor avlcursor;
683
684 SL_ENTER(_("sh_files_setrec"));
685 if (tree != NULL) {
686 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
687 ptr = (dirstack_t *) zAVLNext(&avlcursor))
688 {
689 if (ptr->rdepth < (-1) || ptr->rdepth > 99)
690 {
691 ptr->rdepth = MaxRecursionLevel;
692 }
693
694 if ( (ptr->rdepth == (-1)) &&
695 (ptr->class == SH_LEVEL_ALLIGNORE) &&
696 (sh.flag.checkSum != SH_CHECK_INIT))
697 hash_remove_tree (ptr->name);
698 }
699 }
700 SL_RETURN(0, _("sh_files_setrec"));
701}
702
703int sh_files_setrec ()
704{
705 volatile int ret;
706 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
707 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
708 clear_lists();
709 add_to_dirlist(zdirListOne);
710 add_to_dirlist(zdirListTwo);
711 add_to_filelist(zfileList);
712 sh_files_setrec_int(zdirListOne);
713 ret = sh_files_setrec_int(zdirListTwo);
714 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
715
716 return ret;
717}
718
719zAVLTree * sh_files_deldirstack_int (zAVLTree * ptr)
720{
721 SL_ENTER(_("sh_files_deldirstack"));
722
723 zAVLFreeTree (ptr, free_dirstack);
724
725 SL_RETURN(NULL, _("sh_files_deldirstack"));
726}
727
728int sh_files_deldirstack ()
729{
730 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
731 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
732 zdirListOne = sh_files_deldirstack_int(zdirListOne);
733 zdirListTwo = sh_files_deldirstack_int(zdirListTwo);
734 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
735 return 0;
736}
737
738void sh_files_reset()
739{
740 dirstack_t * ptr;
741 zAVLCursor avlcursor;
742
743 SL_ENTER(_("sh_files_reset"));
744
745 SH_MUTEX_LOCK(mutex_zfiles);
746 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, zfileList); ptr;
747 ptr = (dirstack_t *) zAVLNext(&avlcursor))
748 ptr->checked = 0;
749 SH_MUTEX_UNLOCK(mutex_zfiles);
750 SL_RET0(_("sh_files_reset"));
751}
752
753void sh_dirs_reset()
754{
755 dirstack_t * ptr;
756 zAVLCursor avlcursor1;
757 zAVLCursor avlcursor2;
758
759 SL_ENTER(_("sh_dirs_reset"));
760
761 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
762 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
763 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor1, zdirListOne); ptr;
764 ptr = (dirstack_t *) zAVLNext(&avlcursor1))
765 ptr->checked = 0;
766
767 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor2, zdirListTwo); ptr;
768 ptr = (dirstack_t *) zAVLNext(&avlcursor2))
769 ptr->checked = 0;
770 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
771
772 SL_RET0(_("sh_dirs_reset"));
773}
774
775
776int sh_files_pushfile_prelink (const char * str_s)
777{
778 return (sh_files_pushfile (SH_LEVEL_PRELINK, str_s));
779}
780
781int sh_files_pushfile_user0 (const char * str_s)
782{
783 return (sh_files_pushfile (SH_LEVEL_USER0, str_s));
784}
785
786int sh_files_pushfile_user1 (const char * str_s)
787{
788 return (sh_files_pushfile (SH_LEVEL_USER1, str_s));
789}
790
791int sh_files_pushfile_user2 (const char * str_s)
792{
793 return (sh_files_pushfile (SH_LEVEL_USER2, str_s));
794}
795
796int sh_files_pushfile_user3 (const char * str_s)
797{
798 return (sh_files_pushfile (SH_LEVEL_USER3, str_s));
799}
800
801int sh_files_pushfile_user4 (const char * str_s)
802{
803 return (sh_files_pushfile (SH_LEVEL_USER4, str_s));
804}
805
806
807int sh_files_pushfile_ro (const char * str_s)
808{
809 return (sh_files_pushfile (SH_LEVEL_READONLY, str_s));
810}
811
812int sh_files_pushfile_attr (const char * str_s)
813{
814 return (sh_files_pushfile (SH_LEVEL_ATTRIBUTES, str_s));
815}
816
817int sh_files_pushfile_log (const char * str_s)
818{
819 return (sh_files_pushfile (SH_LEVEL_LOGFILES, str_s));
820}
821
822int sh_files_pushfile_glog (const char * str_s)
823{
824 return (sh_files_pushfile (SH_LEVEL_LOGGROW, str_s));
825}
826
827int sh_files_pushfile_noig (const char * str_s)
828{
829 return (sh_files_pushfile (SH_LEVEL_NOIGNORE, str_s));
830}
831
832int sh_files_pushfile_allig (const char * str_s)
833{
834 return (sh_files_pushfile (SH_LEVEL_ALLIGNORE, str_s));
835}
836
837
838static void sh_files_set_mask (unsigned long * mask,
839 unsigned long val, int act)
840{
841 SL_ENTER(_("sh_files_set_mask"));
842
843 if (act == 0)
844 (*mask) = val;
845 else if (act > 0)
846 (*mask) |= val;
847 else
848 (*mask) &= ~val;
849
850 SL_RET0(_("sh_files_set_mask"));
851}
852
853/* set mask(class)
854 */
855static int sh_files_parse_mask (unsigned long * mask, const char * str)
856{
857 int l, i = 0, act = 0, k = 0;
858 char myword[64];
859
860 SL_ENTER(_("sh_files_parse_mask"));
861
862 myword[0] = '\0';
863
864 if (str == NULL)
865 {
866 SL_RETURN ( (-1), _("sh_files_parse_mask"));
867 }
868 else
869 l = sl_strlen(str);
870
871 while (i < l) {
872
873 if (str[i] == '\0')
874 break;
875
876 if (str[i] == ' ' || str[i] == '\t' || str[i] == ',')
877 {
878 ++i;
879 continue;
880 }
881
882 if (str[i] == '+')
883 {
884 act = +1; ++i;
885 myword[0] = '\0';
886 goto getword;
887 }
888 else if (str[i] == '-')
889 {
890 act = -1; ++i;
891 myword[0] = '\0';
892 goto getword;
893 }
894 else /* a word */
895 {
896 getword:
897 k = 0;
898 while (k < 63 && str[i] != ' ' && str[i] != '\t' && str[i] != ','
899 && str[i] != '+' && str[i] != '-' && str[i] != '\0') {
900 myword[k] = str[i];
901 ++i; ++k;
902 }
903 myword[k] = '\0';
904
905 if (sl_strlen(myword) == 0)
906 {
907 SL_RETURN ( (-1), _("sh_files_parse_mask"));
908 }
909
910/* checksum */
911 if (0 == strcmp(myword, _("CHK")))
912 sh_files_set_mask (mask, MODI_CHK, act);
913/* link */
914 else if (0 == strcmp(myword, _("LNK")))
915 sh_files_set_mask (mask, MODI_LNK, act);
916/* inode */
917 else if (0 == strcmp(myword, _("RDEV")))
918 sh_files_set_mask (mask, MODI_RDEV, act);
919/* inode */
920 else if (0 == strcmp(myword, _("INO")))
921 sh_files_set_mask (mask, MODI_INO, act);
922/* user */
923 else if (0 == strcmp(myword, _("USR")))
924 sh_files_set_mask (mask, MODI_USR, act);
925/* group */
926 else if (0 == strcmp(myword, _("GRP")))
927 sh_files_set_mask (mask, MODI_GRP, act);
928/* mtime */
929 else if (0 == strcmp(myword, _("MTM")))
930 sh_files_set_mask (mask, MODI_MTM, act);
931/* ctime */
932 else if (0 == strcmp(myword, _("CTM")))
933 sh_files_set_mask (mask, MODI_CTM, act);
934/* atime */
935 else if (0 == strcmp(myword, _("ATM")))
936 sh_files_set_mask (mask, MODI_ATM, act);
937/* size */
938 else if (0 == strcmp(myword, _("SIZ")))
939 sh_files_set_mask (mask, MODI_SIZ, act);
940/* file mode */
941 else if (0 == strcmp(myword, _("MOD")))
942 sh_files_set_mask (mask, MODI_MOD, act);
943/* hardlinks */
944 else if (0 == strcmp(myword, _("HLN")))
945 sh_files_set_mask (mask, MODI_HLN, act);
946/* size may grow */
947 else if (0 == strcmp(myword, _("SGROW")))
948 sh_files_set_mask (mask, MODI_SGROW, act);
949/* use prelink */
950 else if (0 == strcmp(myword, _("PRE")))
951 sh_files_set_mask (mask, MODI_PREL, act);
952/* get content */
953 else if (0 == strcmp(myword, _("TXT")))
954 sh_files_set_mask (mask, MODI_TXT, act);
955/* get content */
956 else if (0 == strcmp(myword, _("AUDIT")))
957 sh_files_set_mask (mask, MODI_AUDIT, act);
958 else
959 {
960 SL_RETURN ( (-1), _("sh_files_parse_mask"));
961 }
962 act = 0;
963 myword[0] = '\0';
964 }
965 }
966 SL_RETURN ( (0), _("sh_files_parse_mask"));
967}
968
969int sh_files_redef_prelink(const char * str)
970{
971 return (sh_files_parse_mask(&mask_PRELINK, str));
972}
973int sh_files_redef_user0(const char * str)
974{
975 return (sh_files_parse_mask(&mask_USER0, str));
976}
977int sh_files_redef_user1(const char * str)
978{
979 return (sh_files_parse_mask(&mask_USER1, str));
980}
981int sh_files_redef_user2(const char * str)
982{
983 return (sh_files_parse_mask(&mask_USER2, str));
984}
985int sh_files_redef_user3(const char * str)
986{
987 return (sh_files_parse_mask(&mask_USER3, str));
988}
989int sh_files_redef_user4(const char * str)
990{
991 return (sh_files_parse_mask(&mask_USER4, str));
992}
993int sh_files_redef_readonly(const char * str)
994{
995 return (sh_files_parse_mask(&mask_READONLY, str));
996}
997int sh_files_redef_loggrow(const char * str)
998{
999 return (sh_files_parse_mask(&mask_LOGGROW, str));
1000}
1001int sh_files_redef_logfiles(const char * str)
1002{
1003 return (sh_files_parse_mask(&mask_LOGFILES, str));
1004}
1005int sh_files_redef_attributes(const char * str)
1006{
1007 return (sh_files_parse_mask(&mask_ATTRIBUTES, str));
1008}
1009int sh_files_redef_noignore(const char * str)
1010{
1011 return (sh_files_parse_mask(&mask_NOIGNORE, str));
1012}
1013int sh_files_redef_allignore(const char * str)
1014{
1015 return (sh_files_parse_mask(&mask_ALLIGNORE, str));
1016}
1017
1018unsigned long sh_files_maskof (int class)
1019{
1020 switch (class)
1021 {
1022 case SH_LEVEL_READONLY:
1023 return (unsigned long) (mask_READONLY | MODI_INIT);
1024 case SH_LEVEL_ATTRIBUTES:
1025 return (unsigned long) (mask_ATTRIBUTES | MODI_INIT);
1026 case SH_LEVEL_LOGFILES:
1027 return (unsigned long) (mask_LOGFILES | MODI_INIT);
1028 case SH_LEVEL_LOGGROW:
1029 return (unsigned long) (mask_LOGGROW | MODI_INIT);
1030 case SH_LEVEL_ALLIGNORE:
1031 return (unsigned long) (mask_ALLIGNORE | MODI_INIT);
1032 case SH_LEVEL_NOIGNORE:
1033 return (unsigned long) (mask_NOIGNORE | MODI_INIT);
1034 case SH_LEVEL_USER0:
1035 return (unsigned long) (mask_USER0 | MODI_INIT);
1036 case SH_LEVEL_USER1:
1037 return (unsigned long) (mask_USER1 | MODI_INIT);
1038 case SH_LEVEL_USER2:
1039 return (unsigned long) (mask_USER2 | MODI_INIT);
1040 case SH_LEVEL_USER3:
1041 return (unsigned long) (mask_USER3 | MODI_INIT);
1042 case SH_LEVEL_USER4:
1043 return (unsigned long) (mask_USER4 | MODI_INIT);
1044 case SH_LEVEL_PRELINK:
1045 return (unsigned long) (mask_PRELINK | MODI_INIT);
1046 default:
1047 return (unsigned long) 0;
1048 }
1049}
1050
1051#ifdef HAVE_GLOB_H
1052int sh_files_has_metachar (const char * str)
1053{
1054 SL_ENTER(_("sh_files_has_metachar"));
1055 if (NULL != strchr(str, '*'))
1056 SL_RETURN(1, _("sh_files_has_metachar"));
1057 else if (NULL != strchr(str, '?'))
1058 SL_RETURN(1, _("sh_files_has_metachar"));
1059 else if (NULL != (strchr(str, '[')))
1060 SL_RETURN(1, _("sh_files_has_metachar"));
1061 else
1062 SL_RETURN(0, _("sh_files_has_metachar"));
1063}
1064
1065
1066int sh_files_globerr (const char * epath, int errnum)
1067{
1068 char * p;
1069 char errbuf[SH_ERRBUF_SIZE];
1070
1071 SL_ENTER(_("sh_files_globerr"));
1072
1073 if (errnum == ENOTDIR || errnum == ENOENT)
1074 {
1075 SL_RETURN(0, _("sh_files_globerr"));
1076 }
1077
1078 p = sh_util_safe_name (epath);
1079 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_FI_GLOB,
1080 sh_error_message (errnum, errbuf, sizeof(errbuf)), p);
1081 SH_FREE(p);
1082
1083 SL_RETURN(0, _("sh_files_globerr"));
1084}
1085
1086/* #ifdef HAVE_GLOB_H
1087 */
1088#endif
1089
1090int sh_files_push_file_int (int class, const char * str_s, size_t len,
1091 unsigned long check_flags)
1092{
1093 dirstack_t * new_item_ptr;
1094 char * fileName;
1095 int ret;
1096 volatile int count = 0;
1097
1098 SL_ENTER(_("sh_files_push_file_int"));
1099
1100 fileName = SH_ALLOC(len+1);
1101 sl_strlcpy(fileName, str_s, len+1);
1102
1103 new_item_ptr = (dirstack_t *) SH_ALLOC (sizeof(dirstack_t));
1104
1105 new_item_ptr->name = fileName;
1106 new_item_ptr->class = class;
1107 new_item_ptr->check_flags = check_flags;
1108 new_item_ptr->rdepth = 0;
1109 new_item_ptr->checked = S_FALSE;
1110 new_item_ptr->is_reported = 0;
1111 new_item_ptr->childs_checked = S_FALSE;
1112
1113 SH_MUTEX_LOCK(mutex_zfiles);
1114 if (zfileList == NULL)
1115 {
1116 zfileList = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
1117 if (zfileList == NULL)
1118 {
1119 (void) safe_logger (0, 0, NULL);
1120 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1121 }
1122 }
1123
1124 ret = zAVLInsert (zfileList, new_item_ptr);
1125 SH_MUTEX_UNLOCK(mutex_zfiles);
1126
1127 if (-1 == ret)
1128 {
1129 (void) safe_logger (0, 0, NULL);
1130 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1131 }
1132 else if (3 == ret)
1133 {
1134 if (sh.flag.started != S_TRUE)
1135 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
1136 fileName);
1137 SH_FREE(fileName);
1138 SH_FREE(new_item_ptr);
1139 new_item_ptr = NULL;
1140 }
1141 else
1142 {
1143 int reported;
1144 unsigned long check_flags = sh_files_maskof(class);
1145
1146 if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
1147 {
1148 sh_files_filecheck (class, check_flags, str_s, NULL,
1149 &reported, 0);
1150 if (SH_FFLAG_REPORTED_SET(reported))
1151 sh_files_set_file_reported(str_s);
1152 sh_inotify_add_watch_later(str_s, &sh_file_watches, NULL,
1153 class, check_flags,
1154 SH_INOTIFY_FILE, 0);
1155 }
1156
1157 if (MODI_AUDIT_ENABLED(check_flags))
1158 {
1159 sh_audit_mark(str_s);
1160 }
1161 ++count;
1162 }
1163 SL_RETURN(count, _("sh_files_push_file_int"));
1164}
1165
1166int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_flags);
1167
1168#ifdef HAVE_GLOB_H
1169
1170typedef struct globstack_entry {
1171 char * name;
1172 int class;
1173 unsigned long check_flags;
1174 int rdepth;
1175 short type;
1176 /* struct dirstack_entry * next; */
1177} sh_globstack_t;
1178
1179static zAVLTree * zglobList = NULL;
1180
1181static int sh_files_pushglob (int class, int type, const char * p, int rdepth,
1182 unsigned long check_flags_in, int flag)
1183{
1184 int globstatus = -1;
1185 unsigned int gloop;
1186 glob_t pglob;
1187
1188 volatile int count = 0;
1189 volatile unsigned long check_flags = (flag == 0) ? sh_files_maskof(class) : check_flags_in;
1190
1191 SL_ENTER(_("sh_files_pushglob"));
1192
1193 pglob.gl_offs = 0;
1194 globstatus = glob (p, 0, sh_files_globerr, &pglob);
1195
1196 if (globstatus == 0 && pglob.gl_pathc > 0)
1197 {
1198
1199 if (sh.flag.checkSum != SH_CHECK_INIT)
1200 {
1201 sh_globstack_t * new_item_ptr;
1202 char * fileName;
1203 int ret;
1204
1205 SH_MUTEX_TRYLOCK(mutex_zfiles);
1206 fileName = sh_util_strdup (p);
1207
1208 new_item_ptr = (sh_globstack_t *) SH_ALLOC (sizeof(sh_globstack_t));
1209
1210 new_item_ptr->name = fileName;
1211 new_item_ptr->class = class;
1212 new_item_ptr->check_flags = check_flags;
1213 new_item_ptr->rdepth = rdepth;
1214 new_item_ptr->type = type;
1215
1216 if (zglobList == NULL)
1217 {
1218 zglobList = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
1219 if (zglobList == NULL)
1220 {
1221 (void) safe_logger (0, 0, NULL);
1222 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1223 }
1224 }
1225
1226 ret = zAVLInsert (zglobList, new_item_ptr);
1227
1228 if (ret != 0) /* already in list */
1229 {
1230 SH_FREE(fileName);
1231 SH_FREE(new_item_ptr);
1232 }
1233 SH_MUTEX_TRYLOCK_UNLOCK(mutex_zfiles);
1234 }
1235
1236 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
1237 {
1238 if (type == SH_LIST_FILE)
1239 {
1240 count += sh_files_push_file_int (class, pglob.gl_pathv[gloop],
1241 sl_strlen(pglob.gl_pathv[gloop]), check_flags);
1242 }
1243 else
1244 {
1245 which_dirList = type;
1246
1247 count += sh_files_push_dir_int (class, pglob.gl_pathv[gloop],
1248 sl_strlen(pglob.gl_pathv[gloop]), rdepth, check_flags);
1249 }
1250 }
1251 }
1252 else
1253 {
1254 char * tmp = sh_util_safe_name (p);
1255
1256 if (pglob.gl_pathc == 0
1257#ifdef GLOB_NOMATCH
1258 || globstatus == GLOB_NOMATCH
1259#endif
1260 )
1261 sh_error_handle ((sh.flag.started != S_TRUE) ? SH_ERR_ERR : SH_ERR_NOTICE,
1262 FIL__, __LINE__,
1263 globstatus, MSG_FI_GLOB,
1264 _("No matches found"), tmp);
1265#ifdef GLOB_NOSPACE
1266 else if (globstatus == GLOB_NOSPACE)
1267 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1268 globstatus, MSG_FI_GLOB,
1269 _("Out of memory"), tmp);
1270#endif
1271#ifdef GLOB_ABORTED
1272 else if (globstatus == GLOB_ABORTED)
1273 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1274 globstatus, MSG_FI_GLOB,
1275 _("Read error"), tmp);
1276#endif
1277 else
1278 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1279 globstatus, MSG_FI_GLOB,
1280 _("Unknown error"), tmp);
1281
1282 SH_FREE(tmp);
1283
1284 }
1285
1286 globfree(&pglob);
1287 SL_RETURN(count, _("sh_files_pushglob"));
1288 return count;
1289}
1290
1291void sh_files_check_globFilePatterns()
1292{
1293 sh_globstack_t * testPattern;
1294 zAVLCursor cursor;
1295
1296 SL_ENTER(_("sh_files_check_globPatterns"));
1297
1298 SH_MUTEX_LOCK(mutex_zglob);
1299 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
1300 testPattern;
1301 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
1302 {
1303 if (testPattern->type == SH_LIST_FILE)
1304 {
1305 sh_files_pushglob(testPattern->class, testPattern->type,
1306 testPattern->name, testPattern->rdepth,
1307 testPattern->check_flags, 1);
1308 }
1309 }
1310 SH_MUTEX_UNLOCK(mutex_zglob);
1311 SL_RET0(_("sh_files_check_globPatterns"));
1312}
1313
1314void sh_files_check_globPatterns()
1315{
1316 sh_globstack_t * testPattern;
1317 zAVLCursor cursor;
1318
1319 SL_ENTER(_("sh_files_check_globPatterns"));
1320
1321 SH_MUTEX_LOCK(mutex_zglob);
1322 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
1323 testPattern;
1324 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
1325 {
1326 sh_files_pushglob(testPattern->class, testPattern->type,
1327 testPattern->name, testPattern->rdepth,
1328 testPattern->check_flags, 1);
1329 }
1330 SH_MUTEX_UNLOCK(mutex_zglob);
1331 SL_RET0(_("sh_files_check_globPatterns"));
1332}
1333
1334/* the destructor
1335 */
1336void free_globstack (void * inptr)
1337{
1338 sh_globstack_t * here;
1339
1340 SL_ENTER(_("free_globstack"));
1341 if (inptr == NULL)
1342 SL_RET0(_("free_globstack"));
1343 else
1344 here = (sh_globstack_t *) inptr;
1345
1346 if (here->name != NULL)
1347 SH_FREE(here->name);
1348 SH_FREE(here);
1349 SL_RET0(_("free_globstack"));
1350}
1351
1352int sh_files_delglobstack ()
1353{
1354 SL_ENTER(_("sh_files_delglobstack"));
1355
1356 SH_MUTEX_LOCK(mutex_zglob);
1357 zAVLFreeTree (zglobList, free_globstack);
1358 zglobList = NULL;
1359 SH_MUTEX_UNLOCK(mutex_zglob);
1360
1361 SL_RETURN(0, _("sh_files_delglobstack"));
1362}
1363
1364
1365#else
1366void sh_files_check_globPatterns()
1367{
1368 return;
1369}
1370int sh_files_delglobstack ()
1371{
1372 return 0;
1373}
1374#endif
1375
1376static int sh_files_pushfile (int class, const char * str_s)
1377{
1378 size_t len;
1379 char * tmp;
1380 char * p;
1381
1382 static int reject = 0;
1383
1384 SL_ENTER(_("sh_files_pushfile"));
1385
1386 if (reject == 1)
1387 SL_RETURN((-1),_("sh_files_pushfile"));
1388
1389 /* if we push a filename from the command line, make sure it
1390 * is the only one -- and will stay the only one
1391 */
1392 if (sh.flag.opts == S_TRUE)
1393 {
1394 sh_files_delfilestack ();
1395 sh_files_deldirstack ();
1396 sh_files_delglobstack ();
1397 reject = 1;
1398 }
1399
1400 p = sh_files_parse_input(str_s, &len);
1401 if (!p || len == 0)
1402 SL_RETURN((-1), _("sh_files_pushfile"));
1403
1404 if (len >= PATH_MAX)
1405 {
1406 /* Name too long
1407 */
1408 tmp = sh_util_safe_name (p);
1409 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1410 tmp);
1411 SH_FREE(tmp);
1412 SL_RETURN((-1),_("sh_files_pushfile"));
1413 }
1414 else if (p[0] != '/')
1415 {
1416 /* Not an absolute path
1417 */
1418 tmp = sh_util_safe_name (p);
1419 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1420 tmp);
1421 SH_FREE(tmp);
1422 SL_RETURN((-1),_("sh_files_pushfile"));
1423 }
1424 else
1425 {
1426 /* remove a terminating '/', take care of the
1427 * special case of the root directory.
1428 */
1429 if (p[len-1] == '/' && len > 1)
1430 {
1431 p[len-1] = '\0';
1432 --len;
1433 }
1434 }
1435
1436#ifdef HAVE_GLOB_H
1437 if (0 == sh_files_has_metachar(p))
1438 {
1439 sh_files_push_file_int (class, p, len, sh_files_maskof(class));
1440 }
1441 else
1442 {
1443 sh_files_pushglob (class, SH_LIST_FILE, p, 0, 0, 0);
1444 }
1445
1446#else
1447 sh_files_push_file_int (class, p, len, sh_files_maskof(class));
1448#endif
1449
1450 SH_FREE(p);
1451 SL_RETURN((0),_("sh_files_pushfile"));
1452}
1453
1454
1455/* ------ directories ----- */
1456
1457int sh_files_is_allignore_int (char * str, zAVLTree * tree)
1458{
1459 dirstack_t * ptr;
1460
1461 SL_ENTER(_("sh_files_is_allignore"));
1462
1463 if (tree)
1464 {
1465 ptr = zAVLSearch(tree, str);
1466 if (ptr)
1467 {
1468 if (ptr->class == SH_LEVEL_ALLIGNORE)
1469 SL_RETURN( 1, _("sh_files_is_allignore"));
1470 else
1471 SL_RETURN( 0, _("sh_files_is_allignore"));
1472 }
1473 }
1474 SL_RETURN( 0, _("sh_files_is_allignore"));
1475}
1476
1477int sh_files_is_allignore (char * str)
1478{
1479 int retval = 0;
1480
1481 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1482 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1483 retval = sh_files_is_allignore_int(str, zdirListOne);
1484
1485 if (NULL != zdirListTwo && retval == 0)
1486 {
1487 retval = sh_files_is_allignore_int(str, zdirListTwo);
1488 }
1489 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1490 return retval;
1491}
1492
1493void * sh_dummy_1493_ptr;
1494
1495unsigned long sh_dirs_chk (int which)
1496{
1497 zAVLTree * tree;
1498 zAVLCursor cursor;
1499 dirstack_t * ptr;
1500 dirstack_t * dst_ptr;
1501 int status;
1502 int tmp_reported;
1503 volatile int filetype = SH_FILE_UNKNOWN;
1504 volatile unsigned long dcount = 0;
1505 char * tmp;
1506
1507 SL_ENTER(_("sh_dirs_chk"));
1508
1509 sh_dummy_1493_ptr = (void *) &ptr;
1510
1511 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1512 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1513 if (which == 1)
1514 tree = zdirListOne;
1515 else
1516 tree = zdirListTwo;
1517
1518 for (ptr = (dirstack_t *) zAVLFirst(&cursor, tree); ptr;
1519 ptr = (dirstack_t *) zAVLNext(&cursor))
1520 {
1521 if (sig_urgent > 0) {
1522 goto out;
1523 }
1524
1525 if (ptr->checked == S_FALSE)
1526 {
1527 SH_MUTEX_LOCK(mutex_zfiles);
1528 /* 28 Aug 2001 check the top level directory
1529 */
1530 status = S_FALSE;
1531 dst_ptr = zAVLSearch(zfileList, ptr->name);
1532 if (dst_ptr)
1533 {
1534 if (dst_ptr->checked == S_FALSE)
1535 {
1536 BREAKEXIT(sh_files_filecheck);
1537 tmp_reported = dst_ptr->is_reported;
1538 filetype = sh_files_filecheck (dst_ptr->class, dst_ptr->check_flags,
1539 ptr->name,
1540 NULL, &tmp_reported, 0);
1541 dst_ptr->is_reported = tmp_reported;
1542 (void) handle_filecheck_ret(dst_ptr, NULL, filetype);
1543
1544 dst_ptr->checked = S_TRUE;
1545 status = S_TRUE;
1546 }
1547 else
1548 {
1549 status = S_TRUE;
1550 }
1551 }
1552 SH_MUTEX_UNLOCK(mutex_zfiles);
1553
1554 if (status == S_FALSE)
1555 {
1556 tmp_reported = ptr->is_reported;
1557 filetype = sh_files_filecheck (ptr->class, ptr->check_flags,
1558 ptr->name, NULL, &tmp_reported, 0);
1559 ptr->is_reported = tmp_reported;
1560 (void) handle_filecheck_ret(ptr, NULL, filetype);
1561 }
1562
1563 BREAKEXIT(sh_files_checkdir);
1564 status = sh_files_checkdir (ptr->class, ptr->check_flags,
1565 ptr->rdepth, ptr->name,
1566 ptr->name);
1567
1568 if (status < 0 && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
1569 {
1570 /* directory is missing
1571 */
1572 if (S_FALSE == sh_ignore_chk_del(ptr->name))
1573 {
1574 if (0 != hashreport_missing(ptr->name,
1575 (ptr->class == SH_LEVEL_ALLIGNORE) ?
1576 ShDFLevel[ptr->class] :
1577 ShDFLevel[SH_ERR_T_DIR])) {
1578 tmp = sh_util_safe_name (ptr->name);
1579 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1580 ShDFLevel[ptr->class] :
1581 ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__,
1582 0, MSG_FI_MISS, tmp);
1583 ++sh.statistics.files_report;
1584 SH_FREE(tmp);
1585 }
1586 }
1587 if (sh.flag.reportonce == S_TRUE)
1588 SET_SH_FFLAG_REPORTED(ptr->is_reported);
1589 }
1590 else
1591 {
1592 /* exists (status >= 0), but was missing (reported == TRUE)
1593 */
1594 if (status >= 0 && SH_FFLAG_REPORTED_SET(ptr->is_reported))
1595 {
1596 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
1597 sh_hash_clear_flag(ptr->name, SH_FFLAG_ENOENT);
1598#if 0
1599 /* obsoleted (really?) by the mandatory sh_files_filecheck()
1600 * above, which will catch missing directories anyway
1601 */
1602 tmp = sh_util_safe_name (ptr->name);
1603 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1604 ShDFLevel[ptr->class] :
1605 ShDFLevel[SH_ERR_T_DIR],
1606 FIL__, __LINE__, 0, MSG_FI_ADD,
1607 tmp);
1608 ++sh.statistics.files_report;
1609 SH_FREE(tmp);
1610#endif
1611 }
1612 else if (status == SH_FILE_UNKNOWN)
1613 {
1614 /* catchall
1615 */
1616 tmp = sh_util_safe_name (ptr->name);
1617 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
1618 MSG_FI_FAIL,
1619 tmp);
1620 SH_FREE(tmp);
1621 if (sh.flag.checkSum != SH_CHECK_INIT)
1622 sh_hash_set_visited_true(ptr->name);
1623 }
1624
1625 ++dcount;
1626 }
1627 ptr->checked = S_TRUE;
1628 ptr->childs_checked = S_TRUE;
1629 }
1630
1631 if (sig_urgent > 0) {
1632 goto out;
1633 }
1634
1635 }
1636 out:
1637 ; /* 'label at end of compound statement' */
1638 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1639
1640 SL_RETURN(dcount, _("sh_dirs_chk"));
1641}
1642
1643int sh_files_pushdir_prelink (const char * str_s)
1644{
1645 return (sh_files_pushdir (SH_LEVEL_PRELINK, str_s));
1646}
1647
1648int sh_files_pushdir_user0 (const char * str_s)
1649{
1650 return (sh_files_pushdir (SH_LEVEL_USER0, str_s));
1651}
1652
1653int sh_files_pushdir_user1 (const char * str_s)
1654{
1655 return (sh_files_pushdir (SH_LEVEL_USER1, str_s));
1656}
1657
1658int sh_files_pushdir_user2 (const char * str_s)
1659{
1660 return (sh_files_pushdir (SH_LEVEL_USER2, str_s));
1661}
1662
1663int sh_files_pushdir_user3 (const char * str_s)
1664{
1665 return (sh_files_pushdir (SH_LEVEL_USER3, str_s));
1666}
1667
1668int sh_files_pushdir_user4 (const char * str_s)
1669{
1670 return (sh_files_pushdir (SH_LEVEL_USER4, str_s));
1671}
1672
1673int sh_files_pushdir_attr (const char * str_s)
1674{
1675 return (sh_files_pushdir (SH_LEVEL_ATTRIBUTES, str_s));
1676}
1677
1678int sh_files_pushdir_ro (const char * str_s)
1679{
1680 return (sh_files_pushdir (SH_LEVEL_READONLY, str_s));
1681}
1682
1683int sh_files_pushdir_log (const char * str_s)
1684{
1685 return (sh_files_pushdir (SH_LEVEL_LOGFILES, str_s));
1686}
1687
1688int sh_files_pushdir_glog (const char * str_s)
1689{
1690 return (sh_files_pushdir (SH_LEVEL_LOGGROW, str_s));
1691}
1692
1693int sh_files_pushdir_noig (const char * str_s)
1694{
1695 return (sh_files_pushdir (SH_LEVEL_NOIGNORE, str_s));
1696}
1697
1698int sh_files_pushdir_allig (const char * str_s)
1699{
1700 return (sh_files_pushdir (SH_LEVEL_ALLIGNORE, str_s));
1701}
1702
1703int set_dirList (int which)
1704{
1705 if (which == 2)
1706 which_dirList = SH_LIST_DIR2;
1707 else
1708 which_dirList = SH_LIST_DIR1;
1709 return 0;
1710}
1711
1712int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_flags)
1713{
1714 zAVLTree * tree;
1715 dirstack_t * new_item_ptr;
1716 char * dirName;
1717 int ret;
1718
1719 SL_ENTER(_("sh_files_push_dir_int"));
1720
1721 dirName = SH_ALLOC(len+1);
1722 sl_strlcpy(dirName, tail, len+1);
1723
1724 new_item_ptr = (dirstack_t * ) SH_ALLOC (sizeof(dirstack_t));
1725
1726 new_item_ptr->name = dirName;
1727 new_item_ptr->class = class;
1728 new_item_ptr->check_flags = check_flags;
1729 new_item_ptr->rdepth = rdepth;
1730 new_item_ptr->checked = S_FALSE;
1731 new_item_ptr->is_reported = 0;
1732 new_item_ptr->childs_checked = S_FALSE;
1733
1734 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1735 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1736 if (which_dirList == SH_LIST_DIR1)
1737 {
1738 tree = zdirListOne;
1739 }
1740 else
1741 {
1742 tree = zdirListTwo;
1743 }
1744
1745 if (tree == NULL)
1746 {
1747 tree = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
1748 if (tree == NULL)
1749 {
1750 (void) safe_logger (0, 0, NULL);
1751 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1752 }
1753 if (which_dirList == SH_LIST_DIR1)
1754 zdirListOne = tree;
1755 else
1756 zdirListTwo = tree;
1757 }
1758
1759 ret = zAVLInsert (tree, new_item_ptr);
1760 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1761
1762 if (-1 == ret)
1763 {
1764 (void) safe_logger (0, 0, NULL);
1765 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1766 }
1767 if (3 == ret)
1768 {
1769 if (sh.flag.started != S_TRUE)
1770 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
1771 dirName);
1772 SH_FREE(dirName);
1773 SH_FREE(new_item_ptr);
1774 new_item_ptr = NULL;
1775 }
1776 else
1777 {
1778 if (MODI_AUDIT_ENABLED(check_flags))
1779 {
1780 sh_audit_mark(tail);
1781 }
1782 }
1783 SL_RETURN(0, _("sh_files_push_dir_int"));
1784}
1785
1786static int sh_files_pushdir (int class, const char * str_s)
1787{
1788 char * tmp;
1789 size_t len;
1790 int rdepth = 0;
1791 char * tail = NULL;
1792 char * p;
1793
1794 SL_ENTER(_("sh_files_pushdir"));
1795
1796 if (sh.flag.opts == S_TRUE) {
1797 sh_files_delfilestack ();
1798 sh_files_deldirstack ();
1799 sh_files_delglobstack ();
1800 }
1801
1802 p = sh_files_parse_input(str_s, &len);
1803 if (!p || len == 0)
1804 SL_RETURN((-1),_("sh_files_pushdir"));
1805
1806 if (p[0] != '/')
1807 {
1808 rdepth = strtol(p, &tail, 10);
1809 if (tail == p)
1810 {
1811 SH_FREE(p);
1812 SL_RETURN((-1), _("sh_files_pushdir"));
1813 }
1814 }
1815 else
1816 tail = p;
1817
1818
1819 if (tail == p)
1820 {
1821 /* Setting to an invalid number will force MaxRecursionLevel,
1822 * see sh_files_setrec_int()
1823 */
1824 rdepth = (-2);
1825 }
1826 else if ( (rdepth < (-1) || rdepth > 99) ||
1827 ((rdepth == (-1)) && (class != SH_LEVEL_ALLIGNORE)) )
1828 {
1829 SH_FREE(p);
1830 SL_RETURN((-1), _("sh_files_pushdir"));
1831 }
1832
1833 len = sl_strlen(tail);
1834
1835 if (len >= PATH_MAX)
1836 {
1837 tmp = sh_util_safe_name (tail);
1838 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1839 tmp);
1840 SH_FREE(tmp);
1841 SH_FREE(p);
1842 SL_RETURN((-1), _("sh_files_pushdir"));
1843 }
1844 else if (len < 1)
1845 {
1846 SH_FREE(p);
1847 SL_RETURN((-1), _("sh_files_pushdir"));
1848 }
1849 else if (tail[0] != '/')
1850 {
1851 tmp = sh_util_safe_name (tail);
1852 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1853 tmp);
1854 SH_FREE(tmp);
1855 SH_FREE(p);
1856 SL_RETURN((-1), _("sh_files_pushdir"));
1857 }
1858 else
1859 {
1860 if (tail[len-1] == '/' && len > 1)
1861 {
1862 tail[len-1] = '\0';
1863 --len;
1864 }
1865 }
1866
1867#ifdef HAVE_GLOB_H
1868 if (0 == sh_files_has_metachar(tail))
1869 {
1870 sh_files_push_dir_int (class, tail, len, rdepth, sh_files_maskof(class));
1871 }
1872 else
1873 {
1874 sh_files_pushglob (class, which_dirList, tail, rdepth, 0, 0);
1875 }
1876#else
1877 sh_files_push_dir_int (class, tail, len, rdepth, sh_files_maskof(class));
1878#endif
1879
1880 SH_FREE(p);
1881 SL_RETURN((0), _("sh_files_pushdir"));
1882}
1883
1884/**
1885struct sh_dirent {
1886 char * sh_d_name;
1887 struct sh_dirent * next;
1888};
1889**/
1890
1891void kill_sh_dirlist (struct sh_dirent * dirlist)
1892{
1893 struct sh_dirent * this;
1894
1895 while (dirlist)
1896 {
1897 this = dirlist->next;
1898 SH_FREE(dirlist->sh_d_name);
1899 SH_FREE(dirlist);
1900 dirlist = this;
1901 }
1902 return;
1903}
1904
1905/* -- add an entry to a directory listing
1906 */
1907struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry,
1908 struct sh_dirent * dirlist)
1909{
1910 struct sh_dirent * this;
1911 size_t len;
1912
1913 if (thisEntry == NULL)
1914 return dirlist;
1915
1916 len = sl_strlen(thisEntry->d_name);
1917 if (len == 0)
1918 return dirlist;
1919 ++len;
1920
1921 this = SH_ALLOC(sizeof(struct sh_dirent));
1922 if (!this)
1923 return dirlist;
1924
1925 this->sh_d_name = SH_ALLOC(len);
1926 sl_strlcpy(this->sh_d_name, thisEntry->d_name, len);
1927
1928 this->next = dirlist;
1929 return this;
1930}
1931
1932static int sh_check_hardlinks = S_TRUE;
1933
1934/* Simply sets our boolean as to whether this check is active
1935 */
1936int sh_files_check_hardlinks (const char * opt)
1937{
1938 int i;
1939 SL_ENTER(_("sh_files_check_hardlinks"));
1940 i = sh_util_flagval(opt, &sh_check_hardlinks);
1941 SL_RETURN(i, _("sh_files_check_hardlinks"));
1942}
1943
1944struct sh_hle_struct {
1945 long offset;
1946 char * path;
1947 struct sh_hle_struct * next;
1948};
1949
1950static struct sh_hle_struct * sh_hl_exc = NULL;
1951
1952int sh_files_hle_reg (const char * str)
1953{
1954 long offset;
1955 size_t len;
1956 char * path;
1957
1958 struct sh_hle_struct * tmp = sh_hl_exc;
1959
1960 SL_ENTER(_("sh_files_hle_reg"));
1961
1962 /* Free the linked list if called with NULL argument
1963 */
1964 if (str == NULL)
1965 {
1966 while (tmp)
1967 {
1968 sh_hl_exc = tmp->next;
1969 SH_FREE(tmp->path);
1970 SH_FREE(tmp);
1971 tmp = sh_hl_exc;
1972 }
1973 sh_hl_exc = NULL;
1974 SL_RETURN(0, _("sh_files_hle_reg"));
1975 }
1976
1977 /* We expect 'offset:/path'
1978 */
1979 offset = strtol(str, &path, 0);
1980 if ((path == NULL) || (*path == '\0') || (*path != ':') || (path[1] != '/'))
1981 {
1982 SL_RETURN(-1, _("sh_files_hle_reg"));
1983 }
1984 ++path;
1985 len = 1 + sl_strlen(path);
1986
1987 tmp = SH_ALLOC(sizeof(struct sh_hle_struct));
1988 tmp->path = SH_ALLOC(len);
1989 sl_strlcpy (tmp->path, path, len);
1990 tmp->offset = offset;
1991 tmp->next = sh_hl_exc;
1992 sh_hl_exc = tmp;
1993
1994 SL_RETURN(0, _("sh_files_hle_reg"));
1995}
1996
1997#if !defined(HOST_IS_DARWIN)
1998static int sh_files_hle_test (int offset, char * path)
1999{
2000 struct sh_hle_struct * tmp = sh_hl_exc;
2001
2002 SL_ENTER(_("sh_files_hle_reg"));
2003
2004 while(tmp)
2005 {
2006 if ((offset == tmp->offset) && (0 == strcmp(path, tmp->path)))
2007 {
2008 SL_RETURN(0, _("sh_files_hle_test"));
2009 }
2010 tmp = tmp->next;
2011 }
2012#ifdef HAVE_FNMATCH_H
2013 if ( (offset == 1) && (0 == fnmatch(_("/run/user/*"), path, FNM_PATHNAME)) )
2014 {
2015 /* gvfs directory in /run/user/username/ */
2016 SL_RETURN(0, _("sh_files_hle_test"));
2017 }
2018#endif
2019
2020 SL_RETURN(-1, _("sh_files_hle_test"));
2021}
2022#endif
2023
2024static void * sh_dummy_dirlist;
2025static void * sh_dummy_tmpcat;
2026
2027/* -- Check a single directory and its content. Does not
2028 * check the directory inode itself.
2029 */
2030int sh_files_checkdir (int iclass, unsigned long check_flags,
2031 int idepth, char * iname,
2032 char * relativeName)
2033{
2034 struct sh_dirent * dirlist;
2035 struct sh_dirent * dirlist_orig;
2036
2037 DIR * thisDir = NULL;
2038 struct dirent * thisEntry;
2039 int status;
2040 int dummy = S_FALSE;
2041 dir_type * theDir;
2042 ShFileType checkit;
2043 static unsigned int state = 1;
2044
2045 file_type * theFile;
2046 char * tmpname;
2047 char * tmpcat;
2048 char errbuf[SH_ERRBUF_SIZE];
2049
2050 int rdepth = 0;
2051 int class = 0;
2052 volatile int rdepth_next;
2053 volatile int class_next;
2054 volatile int file_class_next;
2055 volatile unsigned long check_flags_next;
2056 volatile unsigned long file_check_flags_next;
2057
2058 volatile int checked_flag = S_FALSE;
2059 volatile int cchecked_flag = S_FALSE;
2060
2061 dirstack_t * dst_ptr;
2062 dirstack_t * tmp_ptr;
2063
2064 int hardlink_num = 0;
2065#if !defined(HOST_IS_DARWIN)
2066 size_t len;
2067#endif
2068
2069 SL_ENTER(_("sh_files_checkdir"));
2070
2071 if (sig_urgent > 0) {
2072 SL_RETURN((0), _("sh_files_checkdir"));
2073 }
2074
2075 if (iname == NULL || idepth < (-1))
2076 SL_RETURN((-1), _("sh_files_checkdir"));
2077
2078 if (idepth < 0)
2079 {
2080 /* hash_remove_tree (iname); */
2081 SL_RETURN((0), _("sh_files_checkdir"));
2082 }
2083
2084 rdepth = idepth;
2085 class = iclass;
2086
2087 tmpname = sh_util_safe_name (iname);
2088
2089 /* ---- check for obscure name ----
2090 */
2091 if (iclass != SH_LEVEL_ALLIGNORE)
2092 {
2093 sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], iname, S_TRUE);
2094 }
2095
2096 if (flag_err_info == S_TRUE)
2097 {
2098 char pstr[32];
2099
2100 sl_strlcpy(pstr, sh_hash_getpolicy(iclass), sizeof(pstr));
2101 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, pstr, tmpname);
2102 }
2103
2104 /* ---- check input ----
2105 */
2106 if ( sl_strlen(iname) >= PATH_MAX)
2107 {
2108 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2109 MSG_FI_2LONG,
2110 tmpname);
2111 SH_FREE(tmpname);
2112 SL_RETURN((-1), _("sh_files_checkdir"));
2113 }
2114
2115 /* ---- check for absolute path ---- */
2116 if ( iname[0] != '/')
2117 {
2118 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2119 MSG_FI_NOPATH,
2120 tmpname);
2121 SH_FREE(tmpname);
2122 SL_RETURN((-1), _("sh_files_checkdir"));
2123 }
2124
2125 /* ---- stat the directory ----
2126 */
2127 theFile = SH_ALLOC(sizeof(file_type));
2128 sl_strlcpy (theFile->fullpath, iname, PATH_MAX);
2129 theFile->attr_string = NULL;
2130 theFile->link_path = NULL;
2131 theFile->check_flags = check_flags;
2132
2133 (void) relativeName;
2134 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_DIR],
2135 iname,
2136 theFile, NULL, iclass);
2137
2138 if ((sig_termfast == 1) || (sig_terminate == 1))
2139 {
2140 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2141 if (theFile->link_path) SH_FREE(theFile->link_path);
2142 SH_FREE(theFile);
2143 SH_FREE(tmpname);
2144 SL_RETURN((0), _("sh_files_checkdir"));
2145 }
2146
2147 if (status == -1)
2148 {
2149 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2150 if (theFile->link_path) SH_FREE(theFile->link_path);
2151 SH_FREE(theFile);
2152 SH_FREE(tmpname);
2153 SL_RETURN((-1), _("sh_files_checkdir"));
2154 }
2155
2156 if (theFile->c_mode[0] != 'd')
2157 {
2158 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2159 MSG_FI_NODIR,
2160 tmpname);
2161 ++sh.statistics.files_nodir;
2162 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2163 if (theFile->link_path) SH_FREE(theFile->link_path);
2164 SH_FREE(theFile);
2165 SH_FREE(tmpname);
2166 SL_RETURN((-1), _("sh_files_checkdir"));
2167 }
2168
2169 if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
2170 {
2171 sh_inotify_add_watch_later(iname, &sh_file_watches, &status,
2172 iclass, check_flags, SH_INOTIFY_DIR, idepth);
2173 }
2174
2175 hardlink_num = theFile->hardlinks;
2176
2177 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2178 if (theFile->link_path) SH_FREE(theFile->link_path);
2179 SH_FREE(theFile);
2180
2181 /* ---- open directory for reading ----
2182 *
2183 * opendir() will fail with ENOTDIR if the path has been changed
2184 * to a non-directory in between lstat() and opendir().
2185 */
2186 thisDir = opendir (iname);
2187
2188 if (thisDir == NULL)
2189 {
2190 status = errno;
2191 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2192 MSG_E_OPENDIR,
2193 sh_error_message (status, errbuf, sizeof(errbuf)), tmpname);
2194 SH_FREE(tmpname);
2195 SL_RETURN((-1), _("sh_files_checkdir"));
2196 }
2197
2198 theDir = SH_ALLOC(sizeof(dir_type));
2199
2200 theDir->NumRegular = 0;
2201 theDir->NumDirs = 0;
2202 theDir->NumSymlinks = 0;
2203 theDir->NumFifos = 0;
2204 theDir->NumSockets = 0;
2205 theDir->NumCDev = 0;
2206 theDir->NumBDev = 0;
2207 theDir->NumDoor = 0;
2208 theDir->NumPort = 0;
2209 theDir->NumAll = 0;
2210 theDir->TotalBytes = 0;
2211 sl_strlcpy (theDir->DirPath, iname, PATH_MAX);
2212
2213
2214 sh_dummy_dirlist = (void *) &dirlist;
2215 sh_dummy_tmpcat = (void *) &tmpcat;
2216
2217 /* ---- read ----
2218 */
2219 SH_MUTEX_LOCK(mutex_readdir);
2220
2221 dirlist = NULL;
2222 dirlist_orig = NULL;
2223
2224 do {
2225 thisEntry = readdir (thisDir);
2226 if (thisEntry != NULL)
2227 {
2228 ++theDir->NumAll;
2229 if (sl_strcmp (thisEntry->d_name, ".") == 0)
2230 {
2231 ++theDir->NumDirs;
2232 continue;
2233 }
2234 if (sl_strcmp (thisEntry->d_name, "..") == 0)
2235 {
2236 ++theDir->NumDirs;
2237 continue;
2238 }
2239 dirlist = addto_sh_dirlist (thisEntry, dirlist);
2240 }
2241 } while (thisEntry != NULL);
2242
2243 SH_MUTEX_UNLOCK(mutex_readdir);
2244
2245 closedir (thisDir);
2246
2247 ++sh.statistics.dirs_checked;
2248
2249 dirlist_orig = dirlist;
2250
2251 do {
2252
2253 /* If the directory is empty, dirlist = NULL
2254 */
2255 if (!dirlist)
2256 break;
2257
2258 if (sig_termfast == 1)
2259 {
2260 SH_FREE(theDir);
2261 SH_FREE(tmpname);
2262 SL_RETURN((0), _("sh_files_checkdir"));
2263 }
2264
2265 BREAKEXIT(sh_derr);
2266
2267#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
2268 if (0 == (rand_r(&state) % 5)) (void) sh_derr();
2269#else
2270 if (0 == state * (rand() % 5)) (void) sh_derr();
2271#endif
2272
2273 /* ---- Check the file. ----
2274 */
2275 tmpcat = SH_ALLOC(PATH_MAX);
2276 sl_strlcpy(tmpcat, iname, PATH_MAX);
2277 if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/')
2278 sl_strlcat(tmpcat, "/", PATH_MAX);
2279 sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX);
2280
2281 rdepth_next = rdepth - 1;
2282 class_next = class;
2283 check_flags_next = check_flags;
2284 file_class_next = class;
2285 file_check_flags_next = check_flags;
2286 checked_flag = -1;
2287 cchecked_flag = -1;
2288
2289 /* Wed Aug 24 2005 compare against dirListOne, dirListTwo
2290 * this fixes the problem that the directory special file
2291 * is checked with the policy of the parent directory
2292 */
2293 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2294 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2295 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2296
2297 if (dst_ptr)
2298 {
2299 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2300 * this fixes the problem that a policy for the directory
2301 * inode erroneously becomes a policy for the directory itself.
2302 */
2303 file_class_next = dst_ptr->class;
2304 file_check_flags_next = dst_ptr->check_flags;
2305 checked_flag = dst_ptr->checked;
2306 cchecked_flag = dst_ptr->childs_checked;
2307 }
2308
2309 if (checked_flag == -1)
2310 {
2311 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2312
2313 if (dst_ptr)
2314 {
2315 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2316 * this fixes the problem that a policy for the directory
2317 * inode erroneously becomes a policy for the directory itself.
2318 */
2319 file_class_next = dst_ptr->class;
2320 file_check_flags_next = dst_ptr->check_flags;
2321 checked_flag = dst_ptr->checked;
2322 cchecked_flag = dst_ptr->childs_checked;
2323 }
2324 }
2325 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2326
2327 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2328 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2329
2330 if (dst_ptr)
2331 {
2332 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2333 * this fixes the problem that a policy for the directory
2334 * inode erroneously becomes a policy for the directory itself.
2335 */
2336 file_class_next = dst_ptr->class;
2337 file_check_flags_next = dst_ptr->check_flags;
2338 checked_flag = dst_ptr->checked;
2339 /* not set, hence always FALSE */
2340 /* cchecked_flag = dst_ptr->childs_checked; */
2341
2342 if (checked_flag != S_TRUE)
2343 {
2344 /* -- need to check the file itself --
2345 */
2346 if (sh.flag.reportonce == S_TRUE)
2347 dummy = dst_ptr->is_reported;
2348 }
2349 }
2350 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2351
2352 /* ---- Has been checked already. ----
2353 */
2354 if (checked_flag == S_TRUE && cchecked_flag == S_TRUE)
2355 {
2356 /* Mar 11 2004 get ftype for complete directory count
2357 */
2358 checkit = sh_unix_get_ftype(tmpcat);
2359 if (checkit == SH_FILE_DIRECTORY)
2360 {
2361 ++theDir->NumDirs;
2362 }
2363 SH_FREE(tmpcat);
2364 dirlist = dirlist->next;
2365 continue;
2366 }
2367
2368 /* --- May be true, false, or not found. ---
2369 */
2370 if (checked_flag == S_TRUE)
2371 {
2372 /* -- need only the file type --
2373 */
2374 checkit = sh_unix_get_ftype(tmpcat);
2375 }
2376 else
2377 {
2378 /* -- need to check the file itself --
2379 */
2380 /* -- moved up --
2381 * if (dst_ptr && sh.flag.reportonce == S_TRUE)
2382 * dummy = dst_ptr->is_reported;
2383 */
2384
2385 checkit = sh_files_filecheck (file_class_next, file_check_flags_next,
2386 iname,
2387 dirlist->sh_d_name,
2388 &dummy, 0);
2389
2390
2391 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2392 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2393
2394 if (dst_ptr && checked_flag == S_FALSE)
2395 dst_ptr->checked = S_TRUE;
2396
2397 /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag
2398 */
2399 if (dst_ptr && sh.flag.reportonce == S_TRUE)
2400 dst_ptr->is_reported = dummy;
2401
2402 if (dst_ptr)
2403 dst_ptr->childs_checked = S_TRUE;
2404 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2405 }
2406
2407 if (checkit == SH_FILE_REGULAR)
2408 ++theDir->NumRegular;
2409
2410 else if (checkit == SH_FILE_DIRECTORY)
2411 {
2412 ++theDir->NumDirs;
2413
2414 if (rdepth_next >= 0 && cchecked_flag != S_TRUE)
2415 {
2416 rdepth_next = rdepth - 1;
2417
2418 /* check whether the new directory is in the
2419 * list with a recursion depth already defined
2420 */
2421 checked_flag = -1;
2422 cchecked_flag = -1;
2423
2424 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2425 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2426 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2427
2428 if (tmp_ptr)
2429 {
2430 TPT((0, FIL__, __LINE__,
2431 _("msg=<%s -> recursion depth %d\n>"),
2432 tmp_ptr->name, tmp_ptr->rdepth));
2433 rdepth_next = tmp_ptr->rdepth;
2434 class_next = tmp_ptr->class;
2435 check_flags_next = tmp_ptr->check_flags;
2436 /* 28. Aug 2001 reversed
2437 */
2438 cchecked_flag = tmp_ptr->childs_checked;
2439 checked_flag = tmp_ptr->checked;
2440 }
2441
2442 if (checked_flag == -1)
2443 {
2444 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2445
2446 if (tmp_ptr)
2447 {
2448 TPT((0, FIL__, __LINE__,
2449 _("msg=<%s -> recursion depth %d\n>"),
2450 tmp_ptr->name, tmp_ptr->rdepth));
2451 rdepth_next = tmp_ptr->rdepth;
2452 class_next = tmp_ptr->class;
2453 check_flags_next = tmp_ptr->check_flags;
2454 /* 28. Aug 2001 reversed
2455 */
2456 cchecked_flag = tmp_ptr->childs_checked;
2457 checked_flag = tmp_ptr->checked;
2458 }
2459 }
2460
2461 if (tmp_ptr && cchecked_flag == S_FALSE)
2462 {
2463 tmp_ptr->childs_checked = S_TRUE;
2464 /*
2465 * 04. Feb 2006 avoid double checking
2466 */
2467 tmp_ptr->checked = S_TRUE;
2468 }
2469 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2470
2471 if (cchecked_flag == S_FALSE)
2472 {
2473 sh_files_checkdir (class_next, check_flags_next, rdepth_next,
2474 tmpcat, dirlist->sh_d_name);
2475 /*
2476 tmp_ptr->childs_checked = S_TRUE;
2477 tmp_ptr->checked = S_TRUE;
2478 */
2479 }
2480 else if (checked_flag == -1)
2481 sh_files_checkdir (class_next, check_flags_next, rdepth_next,
2482 tmpcat, dirlist->sh_d_name);
2483
2484 }
2485 }
2486
2487 else if (checkit == SH_FILE_SYMLINK) ++theDir->NumSymlinks;
2488 else if (checkit == SH_FILE_FIFO) ++theDir->NumFifos;
2489 else if (checkit == SH_FILE_SOCKET) ++theDir->NumSockets;
2490 else if (checkit == SH_FILE_CDEV) ++theDir->NumCDev;
2491 else if (checkit == SH_FILE_BDEV) ++theDir->NumBDev;
2492 else if (checkit == SH_FILE_DOOR) ++theDir->NumDoor;
2493 else if (checkit == SH_FILE_PORT) ++theDir->NumPort;
2494
2495 SH_FREE(tmpcat);
2496
2497 if ((sig_termfast == 1) || (sig_terminate == 1))
2498 {
2499 SH_FREE(theDir);
2500 sh_dummy_dirlist = NULL;
2501 SH_FREE(tmpname);
2502 SL_RETURN((0), _("sh_files_checkdir"));
2503 }
2504
2505 dirlist = dirlist->next;
2506
2507 /* -- moved up, only affects zfileList anyway
2508 * if (dst_ptr)
2509 * dst_ptr->childs_checked = S_TRUE;
2510 */
2511
2512 } while (dirlist != NULL);
2513
2514 if (flag_err_info == S_TRUE)
2515 {
2516 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
2517 theDir->NumDirs,
2518 theDir->NumRegular,
2519 theDir->NumSymlinks,
2520 theDir->NumFifos,
2521 theDir->NumSockets,
2522 theDir->NumCDev,
2523 theDir->NumBDev);
2524 }
2525
2526 kill_sh_dirlist (dirlist_orig);
2527
2528#if !defined(HOST_IS_DARWIN)
2529 /*
2530 * Hardlink check; not done on MacOS X because of resource forks
2531 */
2532 if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir->NumDirs))
2533 {
2534 if (0 != sh_files_hle_test(hardlink_num-theDir->NumDirs, iname))
2535 {
2536 len = strlen(tmpname);
2537 if (sl_ok_adds(len, 256))
2538 len += 256;
2539 tmpcat = SH_ALLOC(len);
2540 sl_snprintf(tmpcat, len,
2541 _("%s: subdirectory count (%d) != hardlinks (%d)"),
2542 tmpname, theDir->NumDirs, hardlink_num);
2543 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2544 MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir"));
2545 SH_FREE(tmpcat);
2546 }
2547 }
2548#endif
2549
2550 SH_FREE(tmpname);
2551 SH_FREE(theDir);
2552
2553 sh_dummy_dirlist = NULL;
2554
2555 SL_RETURN((0), _("sh_files_checkdir"));
2556}
2557
2558void sh_files_fixup_mask (int class, unsigned long * check_flags)
2559{
2560 if (class == SH_LEVEL_ALLIGNORE)
2561 MODI_SET((*check_flags), MODI_ALLIGNORE);
2562 sh_tiger_get_mask_hashtype(check_flags);
2563 return;
2564}
2565
2566int get_the_fd (SL_TICKET ticket);
2567
2568static int sh_use_rsrc = S_FALSE;
2569
2570int sh_files_use_rsrc(const char * str)
2571{
2572 return sh_util_flagval(str, &sh_use_rsrc);
2573}
2574
2575static void * sh_dummy_fileName;
2576static void * sh_dummy_tmpname;
2577static void * sh_dummy_tmpdir;
2578
2579ShFileType sh_files_filecheck (int class, unsigned long check_flags,
2580 const char * dirName,
2581 const char * infileName,
2582 int * reported,
2583 int rsrcflag)
2584{
2585 /* 28 Aug 2001 allow NULL fileName
2586 */
2587 char * fullpath;
2588 char fileHash[2*(KEY_LEN + 1)];
2589 int status;
2590 file_type * theFile;
2591 char * tmpdir;
2592 char * tmpname;
2593 const char * fileName;
2594#if !defined(O_NOATIME)
2595 struct utimbuf utime_buf;
2596#endif
2597 static unsigned int state = 1;
2598 char sc;
2599
2600 SL_ENTER(_("sh_files_filecheck"));
2601
2602 fullpath = SH_ALLOC(PATH_MAX);
2603 theFile = SH_ALLOC(sizeof(file_type));
2604
2605 /* Take the address to keep gcc from putting it into a register.
2606 * Avoids the 'clobbered by longjmp' warning.
2607 */
2608 sh_dummy_fileName = (void *) &fileName;
2609 sh_dummy_tmpname = (void *) &tmpname;
2610 sh_dummy_tmpdir = (void *) &tmpdir;
2611
2612 BREAKEXIT(sh_derr);
2613
2614#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
2615 if (0 == (rand_r(&state) % 2)) (void) sh_derr();
2616#else
2617 if (0 == state * (rand() % 2)) (void) sh_derr();
2618#endif
2619
2620 if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0')
2621 && (infileName[0] == '/') && (infileName[1] == '\0'))
2622 {
2623 fileName = NULL;
2624 }
2625 else
2626 {
2627 fileName = infileName;
2628 }
2629
2630 /* fileName may be NULL if this is a directory
2631 */
2632 if (dirName == NULL /* || fileName == NULL */)
2633 {
2634 SH_MUTEX_LOCK(mutex_thread_nolog);
2635 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL);
2636 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2637 SH_FREE(fullpath);
2638 SH_FREE(theFile);
2639 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2640 }
2641
2642 if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) &&
2643 (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME],
2644 fileName, S_FALSE)))
2645 {
2646 if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0'))
2647 {
2648 tmpname = sh_util_safe_name (fileName);
2649 SH_MUTEX_LOCK(mutex_thread_nolog);
2650 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2651 MSG_FI_OBSC2,
2652 "", tmpname);
2653 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2654 SH_FREE(tmpname);
2655 }
2656 else
2657 {
2658 tmpdir = sh_util_safe_name (dirName);
2659 tmpname = sh_util_safe_name (fileName);
2660 SH_MUTEX_LOCK(mutex_thread_nolog);
2661 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2662 MSG_FI_OBSC2,
2663 tmpdir, tmpname);
2664 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2665 SH_FREE(tmpname);
2666 SH_FREE(tmpdir);
2667 }
2668 }
2669
2670 /* sh_files_fullpath accepts NULL fileName
2671 */
2672 if (0 != sh_files_fullpath (dirName, fileName, fullpath))
2673 {
2674 tmpdir = sh_util_safe_name (dirName);
2675 tmpname = sh_util_safe_name (fileName);
2676 SH_MUTEX_LOCK(mutex_thread_nolog);
2677 sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0,
2678 MSG_FI_2LONG2,
2679 tmpdir, tmpname);
2680 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2681 SH_FREE(tmpname);
2682 SH_FREE(tmpdir);
2683 SH_FREE(fullpath);
2684 SH_FREE(theFile);
2685 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2686 }
2687
2688 /* stat the file and determine checksum (if a regular file)
2689 */
2690 sl_strlcpy (theFile->fullpath, fullpath, PATH_MAX);
2691 theFile->check_flags = check_flags /* sh_files_maskof(class) */;
2692 theFile->file_reported = (*reported);
2693 theFile->attr_string = NULL;
2694 theFile->link_path = NULL;
2695
2696 TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"), fullpath));
2697
2698 status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ?
2699 ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE],
2700 fileName,
2701 theFile, fileHash, class);
2702
2703 if (status != 0)
2704 {
2705 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
2706 fullpath, status));
2707 if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
2708 sh_hash_set_visited_true (fullpath);
2709 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2710 if (theFile->link_path) SH_FREE(theFile->link_path);
2711 SH_FREE(fullpath);
2712 SH_FREE(theFile);
2713 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2714 }
2715
2716 if (sig_termfast == 1) {
2717 goto ret_point;
2718 }
2719
2720 /* report
2721 */
2722 if ((flag_err_debug == S_TRUE) && (theFile->c_mode[0] == '-'))
2723 {
2724 tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
2725 SH_MUTEX_LOCK(mutex_thread_nolog);
2726 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM,
2727 fileHash, tmpname);
2728 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2729 SH_FREE(tmpname);
2730 }
2731 ++sh.statistics.files_checked;
2732
2733 if ( sh.flag.checkSum == SH_CHECK_INIT)
2734 {
2735 if (class == SH_LEVEL_ALLIGNORE)
2736 MODI_SET(theFile->check_flags, MODI_ALLIGNORE);
2737 if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
2738 MODI_SET(theFile->check_flags, MODI_NOCHECK);
2739 sh_tiger_get_mask_hashtype(&(theFile->check_flags));
2740 sh_dbIO_data_write (theFile, fileHash);
2741 }
2742 else if (sh.flag.checkSum == SH_CHECK_CHECK
2743 /* && theFile.c_mode[0] == '-' */
2744 /* && class != SH_LEVEL_ALLIGNORE */
2745 )
2746 {
2747 if (sh.flag.update == S_TRUE)
2748 {
2749 if (class == SH_LEVEL_ALLIGNORE)
2750 MODI_SET(theFile->check_flags, MODI_ALLIGNORE);
2751 if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
2752 MODI_SET(theFile->check_flags, MODI_NOCHECK);
2753 sh_tiger_get_mask_hashtype(&(theFile->check_flags));
2754 }
2755 sh_hash_compdata (class, theFile, fileHash, NULL, -1);
2756 }
2757
2758 (*reported) = theFile->file_reported;
2759
2760 /* reset the access time
2761 */
2762#if !defined(O_NOATIME)
2763 if (class == SH_LEVEL_NOIGNORE && (theFile->check_flags & MODI_ATM) != 0)
2764 {
2765 utime_buf.actime = (time_t) theFile->atime;
2766 utime_buf.modtime = (time_t) theFile->mtime;
2767
2768 retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf);
2769 }
2770#endif
2771
2772#if defined(HOST_IS_DARWIN)
2773 /*
2774 * Check for resource fork
2775 */
2776 if ( (sh_use_rsrc == S_TRUE) && (theFile->c_mode[0] != 'd') && (rsrcflag == 0) )
2777 {
2778 int dummy;
2779 static int rsrc_init = 0;
2780 static char rsrc[17];
2781 char * testpath = SH_ALLOC(PATH_MAX);
2782
2783 if (rsrc_init == 0) {
2784 sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17);
2785 rsrc_init = 1;
2786 }
2787 sl_strlcpy (testpath, fullpath, PATH_MAX);
2788 sl_strlcat (testpath, "/", PATH_MAX);
2789 sl_strlcat (testpath, rsrc, PATH_MAX);
2790
2791 if (sl_strlen(testpath) == (17 + sl_strlen(fullpath)))
2792 {
2793 if (S_TRUE == sh_unix_file_exists (testpath))
2794 {
2795 sh_files_filecheck (class, check_flags, fullpath, rsrc, &dummy, 1);
2796 }
2797 }
2798 SH_FREE(testpath);
2799 }
2800#else
2801 (void) rsrcflag; /* avoid compiler warning */
2802#endif
2803
2804 ret_point:
2805
2806 sc = theFile->c_mode[0];
2807
2808 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2809 if (theFile->link_path) SH_FREE(theFile->link_path);
2810 SH_FREE(fullpath);
2811 SH_FREE(theFile);
2812
2813 switch (sc)
2814 {
2815 case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck"));
2816 case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck"));
2817 case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck"));
2818 case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck"));
2819 case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck"));
2820 case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck"));
2821 case 'D': SL_RETURN(SH_FILE_DOOR, _("sh_files_filecheck"));
2822 case 'P': SL_RETURN(SH_FILE_PORT, _("sh_files_filecheck"));
2823 case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck"));
2824 default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2825 }
2826
2827 /* notreached */
2828}
2829
2830/* concatenate statpath = testdir"/"d_name
2831 */
2832static int sh_files_fullpath (const char * testdir, const char * d_name,
2833 char * statpath)
2834{
2835 int llen = 0;
2836
2837 SL_ENTER(_("sh_files_fullpath"));
2838
2839 if (testdir != NULL)
2840 {
2841 if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) )
2842 SL_RETURN((-1),_("sh_files_fullpath"));
2843 sl_strlcpy(statpath, testdir, PATH_MAX - 1);
2844 }
2845 if (d_name != NULL)
2846 {
2847 if (llen > 1 || statpath[0] != '/')
2848 sl_strlcat(statpath, "/", PATH_MAX);
2849 if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX)
2850 SL_RETURN((-1),_("sh_files_fullpath"));
2851 sl_strlcat(statpath, d_name, PATH_MAX);
2852 }
2853 if (statpath == NULL)
2854 SL_RETURN((-1),_("sh_files_fullpath"));
2855 SL_RETURN((0),_("sh_files_fullpath"));
2856}
2857
2858/* -----------------------------------
2859 * Routines required for inotify
2860 * -----------------------------------
2861 */
2862int sh_files_search_dir(char * name, int * class,
2863 unsigned long *check_flags, int *reported,
2864 int * rdepth)
2865{
2866 volatile int retval = 0;
2867#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2868 sh_globstack_t * testPattern;
2869 zAVLCursor cursor;
2870#endif
2871 dirstack_t * item;
2872
2873 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2874 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2875
2876 item = zAVLSearch(zdirListOne, name);
2877
2878 if (item)
2879 {
2880 *check_flags = item->check_flags;
2881 *class = item->class;
2882 *reported = item->is_reported;
2883 *rdepth = item->rdepth;
2884 item->checked = S_FALSE;
2885 item->childs_checked = S_FALSE;
2886 item->is_reported = S_FALSE;
2887 retval = 1;
2888 goto out;
2889 }
2890
2891 item = zAVLSearch(zdirListTwo, name);
2892
2893 if (item)
2894 {
2895 *check_flags = item->check_flags;
2896 *class = item->class;
2897 *reported = item->is_reported;
2898 *rdepth = item->rdepth;
2899 item->checked = S_FALSE;
2900 item->childs_checked = S_FALSE;
2901 item->is_reported = S_FALSE;
2902 retval = 1;
2903 goto out;
2904 }
2905
2906#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2907 SH_MUTEX_LOCK(mutex_zglob);
2908 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
2909 testPattern;
2910 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
2911 {
2912 if (testPattern->type == SH_LIST_DIR1 ||
2913 testPattern->type == SH_LIST_DIR2)
2914 {
2915 if (0 == fnmatch(testPattern->name, name, FNM_PATHNAME|FNM_PERIOD))
2916 {
2917 *check_flags = testPattern->check_flags;
2918 *class = testPattern->class;
2919 *rdepth = testPattern->rdepth;
2920 retval = 1;
2921 break;
2922 }
2923
2924 }
2925 }
2926 SH_MUTEX_UNLOCK(mutex_zglob);
2927#endif
2928 out:
2929 ; /* 'label at end of compound statement' */
2930 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2931 return retval;
2932}
2933
2934int sh_files_search_file(char * name, int * class,
2935 unsigned long *check_flags, int *reported)
2936{
2937 volatile int retval = 0;
2938#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2939 sh_globstack_t * testPattern;
2940 zAVLCursor cursor;
2941#endif
2942 dirstack_t * item;
2943
2944 SH_MUTEX_LOCK(mutex_zfiles);
2945 item = zAVLSearch(zfileList, name);
2946
2947 if (item)
2948 {
2949 *check_flags = item->check_flags;
2950 *class = item->class;
2951 *reported = item->is_reported;
2952 retval = 1;
2953 }
2954 SH_MUTEX_UNLOCK(mutex_zfiles);
2955
2956#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2957 if (retval == 0)
2958 {
2959 SH_MUTEX_LOCK(mutex_zglob);
2960 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
2961 testPattern;
2962 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
2963 {
2964 if (testPattern->type == SH_LIST_FILE)
2965 {
2966 if (0 == fnmatch(testPattern->name, name,
2967 FNM_PATHNAME|FNM_PERIOD))
2968 {
2969 *check_flags = testPattern->check_flags;
2970 *class = testPattern->class;
2971 retval = 1;
2972 break;
2973 }
2974
2975 }
2976 }
2977 SH_MUTEX_UNLOCK(mutex_zglob);
2978 }
2979#endif
2980
2981 return retval;
2982}
2983
2984void sh_files_set_file_reported(const char * name)
2985{
2986 dirstack_t * item;
2987
2988 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2989 item = zAVLSearch(zfileList, name);
2990
2991 if (item)
2992 {
2993 if (sh.flag.reportonce == S_TRUE)
2994 SET_SH_FFLAG_REPORTED(item->is_reported);
2995 }
2996 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2997 return;
2998}
2999
3000void sh_files_clear_file_reported(const char * name)
3001{
3002 dirstack_t * item;
3003
3004 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
3005 item = zAVLSearch(zfileList, name);
3006
3007 if (item)
3008 {
3009 CLEAR_SH_FFLAG_REPORTED(item->is_reported);
3010 }
3011 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
3012 return;
3013}
3014
3015/* -----------------------------------
3016 *
3017 * The following two routines serve to
3018 * verify that the user has selected
3019 * a proper setup for file policies.
3020 *
3021 * -----------------------------------
3022 */
3023static int check_file(char * name)
3024{
3025 dirstack_t * pfilL;
3026 zAVLCursor cursor;
3027 volatile int retval = -1;
3028
3029 SL_ENTER(_("check_file"));
3030
3031 if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name))
3032 SL_RETURN(0, _("check_file"));
3033
3034 for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL;
3035 pfilL = (dirstack_t *) zAVLNext (&cursor))
3036 {
3037 if (0 == strcmp(name, pfilL->name) &&
3038 (pfilL->check_flags & MODI_ATM) == 0 &&
3039 (pfilL->check_flags & MODI_CTM) == 0 &&
3040 (pfilL->check_flags & MODI_MTM) == 0)
3041 {
3042 retval = 0;
3043 break;
3044 }
3045 }
3046
3047 SL_RETURN(retval, _("check_file"));
3048}
3049
3050static void * sh_dummy_pdirL;
3051
3052int sh_files_test_setup_int (zAVLTree * tree)
3053{
3054 int dlen, flen;
3055 zAVLCursor cursor1;
3056 zAVLCursor cursor2;
3057
3058 dirstack_t * pdirL;
3059 dirstack_t * pfilL;
3060
3061 SL_ENTER(_("sh_files_test_setup"));
3062
3063 sh_dummy_pdirL = (void *) &pdirL;
3064
3065 for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL;
3066 pdirL = (dirstack_t *) zAVLNext (&cursor1))
3067 {
3068 dlen = strlen(pdirL->name);
3069
3070 SH_MUTEX_LOCK(mutex_zfiles);
3071 for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL;
3072 pfilL = (dirstack_t *) zAVLNext (&cursor2))
3073 {
3074 flen = strlen(pfilL->name);
3075
3076 /* check whether file is in tree of dir
3077 */
3078 if ((pfilL->class == SH_LEVEL_READONLY) ||
3079 (pfilL->class == SH_LEVEL_NOIGNORE))
3080 {
3081 ; /* do nothing */
3082 }
3083 else
3084 {
3085 if ((flen > (dlen+1)) &&
3086 (pfilL->name[dlen] == '/') &&
3087 (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/
3088 (0 == strncmp(pfilL->name, pdirL->name, dlen)))
3089 {
3090 if ((pdirL->check_flags & MODI_ATM) != 0 ||
3091 (pdirL->check_flags & MODI_MTM) != 0 ||
3092 (pdirL->check_flags & MODI_CTM) != 0)
3093 {
3094 if (check_file (pdirL->name) != 0)
3095 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL,
3096 pdirL->name, pfilL->name);
3097 }
3098 }
3099 }
3100 }
3101 SH_MUTEX_UNLOCK(mutex_zfiles);
3102 }
3103
3104 SL_RETURN((0), _("sh_files_test_setup"));
3105}
3106
3107int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList)
3108{
3109 int retval = 0;
3110 zAVLCursor cursor;
3111 dirstack_t * first;
3112
3113 for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first;
3114 first = (dirstack_t *) zAVLNext (&cursor))
3115 {
3116
3117 if (NULL != zAVLSearch(secondList, first->name))
3118 {
3119 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
3120 first->name);
3121 retval = 1;
3122 }
3123 }
3124 return retval;
3125}
3126
3127extern void aud_exit (const char * file, int line, int fd);
3128
3129int sh_files_test_setup ()
3130{
3131 int retval;
3132
3133 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
3134 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
3135 /* Test for modifications allowed in ReadOnly directory
3136 */
3137 sh_files_test_setup_int (zdirListOne);
3138 sh_files_test_setup_int (zdirListTwo);
3139
3140 /* Test for files/dirz defined twice
3141 */
3142 retval = sh_files_test_double (zdirListOne, zdirListTwo);
3143 if (retval != 0)
3144 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
3145
3146 retval = sh_files_test_double (zdirListTwo, zdirListOne);
3147 if (retval != 0)
3148 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
3149 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
3150
3151 return 0;
3152}
3153
3154#endif
3155
3156#ifdef SH_CUTEST
3157#include "CuTest.h"
3158
3159void Test_file_lists (CuTest *tc)
3160{
3161#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
3162
3163 extern int hash_remove_tree_test(char * s, char * fullpath, size_t len_s);
3164
3165 char * test;
3166 int ret;
3167
3168 sh_files_pushfile_ro("/usr/test");
3169 sh_files_pushfile_ro("/usr/bin/test");
3170 sh_files_pushfile_ro("/usr/bin/foo/test");
3171
3172 sh_files_pushdir_ro("/usr");
3173 sh_files_pushdir_attr("/usr/bin");
3174 sh_files_pushdir_ro("/usr/bin/foo");
3175
3176 add_to_dirlist(zdirListOne);
3177 add_to_dirlist(zdirListTwo);
3178 add_to_filelist(zfileList);
3179
3180 test = sh_files_findfile("/usr/tes");
3181 CuAssertTrue(tc, test == NULL);
3182 test = sh_files_findfile("/usr/test");
3183 CuAssertPtrNotNull(tc, test);
3184 test = sh_files_findfile("/usr/testi");
3185 CuAssertTrue(tc, test == NULL);
3186 test = sh_files_findfile("/test");
3187 CuAssertTrue(tc, test == NULL);
3188
3189 test = sh_files_find_mostspecific_dir("/usr/bin/foo/test");
3190 CuAssertStrEquals(tc, "/usr/bin/foo", test);
3191 test = sh_files_find_mostspecific_dir("/usr/bin/test");
3192 CuAssertStrEquals(tc, "/usr/bin", test);
3193 test = sh_files_find_mostspecific_dir("/usr/test");
3194 CuAssertStrEquals(tc, "/usr", test);
3195 test = sh_files_find_mostspecific_dir("/test");
3196 CuAssertTrue(tc, test == NULL);
3197 test = sh_files_find_mostspecific_dir("/usr/foo/test");
3198 CuAssertStrEquals(tc, "/usr", test);
3199
3200 test = sh_files_find_mostspecific_dir("/usr/bin");
3201 CuAssertStrEquals(tc, "/usr/bin", test);
3202
3203 ret = hash_remove_tree_test("/usr", "/usr/test", strlen("/usr"));
3204 CuAssertIntEquals(tc, S_FALSE, ret);
3205 ret = hash_remove_tree_test("/usr", "/usr/testi", strlen("/usr"));
3206 CuAssertIntEquals(tc, S_TRUE, ret);
3207 ret = hash_remove_tree_test("/usr", "/usr/tes", strlen("/usr"));
3208 CuAssertIntEquals(tc, S_TRUE, ret);
3209
3210 ret = hash_remove_tree_test("/usr/bin", "/usr/test", strlen("/usr/bin"));
3211 CuAssertIntEquals(tc, S_FALSE, ret);
3212 ret = hash_remove_tree_test("/usr/bin", "/usr/testi", strlen("/usr/bin"));
3213 CuAssertIntEquals(tc, S_FALSE, ret);
3214 ret = hash_remove_tree_test("/usr/bin", "/usr/tes", strlen("/usr/bin"));
3215 CuAssertIntEquals(tc, S_FALSE, ret);
3216
3217 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/test", strlen("/usr/bin"));
3218 CuAssertIntEquals(tc, S_FALSE, ret);
3219 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/testi", strlen("/usr/bin"));
3220 CuAssertIntEquals(tc, S_TRUE, ret);
3221 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/tes", strlen("/usr/bin"));
3222 CuAssertIntEquals(tc, S_TRUE, ret);
3223
3224 ret = hash_remove_tree_test("/usr/bin", "/usr/bin", strlen("/usr/bin"));
3225 CuAssertIntEquals(tc, S_TRUE, ret);
3226 ret = hash_remove_tree_test("/usr", "/usr", strlen("/usr"));
3227 CuAssertIntEquals(tc, S_TRUE, ret);
3228 ret = hash_remove_tree_test("/usr", "/usrbin", strlen("/usr"));
3229 CuAssertIntEquals(tc, S_FALSE, ret);
3230 ret = hash_remove_tree_test("/", "/usrbin", strlen("/"));
3231 CuAssertIntEquals(tc, S_TRUE, ret);
3232 ret = hash_remove_tree_test("/", "/usr", strlen("/"));
3233 CuAssertIntEquals(tc, S_FALSE, ret);
3234
3235#else
3236 (void) tc; /* fix compiler warning */
3237 return;
3238#endif
3239}
3240
3241void Test_file_dequote (CuTest *tc)
3242{
3243#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
3244
3245 char str1[] = "1234567890";
3246 char str1a[] = "123456\\\"789\\r";
3247 char str1b[] = "12345678\\r9";
3248 char str1c[] = "12345678\\x0a_9";
3249 char str1d[] = "12345678\\007_9";
3250 char str1e[] = "123456789\\\\";
3251
3252 char str2[] = "1234567890\\xw";
3253 char str3[] = "1234567890\\xw99";
3254 char str4[] = "1234567890\\0ww";
3255 char str5[] = "12345\\g67890";
3256 char str6[] = "1234567890\\009a";
3257
3258 char *s, *p, *q;
3259 size_t lo, lr;
3260
3261 s = SH_ALLOC(64); sl_strlcpy(s, str1, 64); p = s; lo = strlen(s); lr = lo;
3262 q = sh_files_C_dequote(s, &lr);
3263 CuAssertPtrNotNull(tc, q);
3264 CuAssertTrue(tc, p == q);
3265 CuAssertTrue(tc, lr == lo);
3266
3267 s = SH_ALLOC(64); sl_strlcpy(s, str1a, 64); p = s; lo = strlen(s); lr = lo;
3268 q = sh_files_C_dequote(s, &lr);
3269 CuAssertPtrNotNull(tc, q);
3270 CuAssertTrue(tc, p != q);
3271 CuAssertTrue(tc, 0 == strcmp(q, "123456\"789\r"));
3272 CuAssertTrue(tc, lr == (lo-2));
3273
3274 s = SH_ALLOC(64); sl_strlcpy(s, str1b, 64); p = s; lo = strlen(s); lr = lo;
3275 q = sh_files_C_dequote(s, &lr);
3276 CuAssertPtrNotNull(tc, q);
3277 CuAssertTrue(tc, p != q);
3278 CuAssertTrue(tc, 0 == strcmp(q, "12345678\r9"));
3279 CuAssertTrue(tc, lr == (lo-1));
3280
3281 s = SH_ALLOC(64); sl_strlcpy(s, str1c, 64); p = s; lo = strlen(s); lr = lo;
3282 q = sh_files_C_dequote(s, &lr);
3283 CuAssertPtrNotNull(tc, q);
3284 CuAssertTrue(tc, p != q);
3285 CuAssertTrue(tc, 0 == strcmp(q, "12345678\x0a_9"));
3286 CuAssertTrue(tc, lr == (lo-3));
3287
3288 s = SH_ALLOC(64); sl_strlcpy(s, str1d, 64); p = s; lo = strlen(s); lr = lo;
3289 q = sh_files_C_dequote(s, &lr);
3290 CuAssertPtrNotNull(tc, q);
3291 CuAssertTrue(tc, p != q);
3292 CuAssertTrue(tc, 0 == strcmp(q, "12345678\007_9"));
3293 CuAssertTrue(tc, lr == (lo-3));
3294
3295 s = SH_ALLOC(64); sl_strlcpy(s, str1e, 64); p = s; lo = strlen(s); lr = lo;
3296 q = sh_files_C_dequote(s, &lr);
3297 CuAssertPtrNotNull(tc, q);
3298 CuAssertTrue(tc, p != q);
3299 CuAssertTrue(tc, 0 == strcmp(q, "123456789\\"));
3300 CuAssertTrue(tc, lr == (lo-1));
3301
3302 s = SH_ALLOC(64); sl_strlcpy(s, str2, 64); p = s; lo = strlen(s); lr = lo;
3303 q = sh_files_C_dequote(s, &lr);
3304 CuAssertTrue(tc, q == NULL);
3305 CuAssertTrue(tc, lr == 0);
3306
3307 s = SH_ALLOC(64); sl_strlcpy(s, str3, 64); p = s; lo = strlen(s); lr = lo;
3308 q = sh_files_C_dequote(s, &lr);
3309 CuAssertTrue(tc, q == NULL);
3310 CuAssertTrue(tc, lr == 0);
3311
3312 s = SH_ALLOC(64); sl_strlcpy(s, str4, 64); p = s; lo = strlen(s); lr = lo;
3313 q = sh_files_C_dequote(s, &lr);
3314 CuAssertTrue(tc, q == NULL);
3315 CuAssertTrue(tc, lr == 0);
3316
3317 s = SH_ALLOC(64); sl_strlcpy(s, str5, 64); p = s; lo = strlen(s); lr = lo;
3318 q = sh_files_C_dequote(s, &lr);
3319 CuAssertTrue(tc, q == NULL);
3320 CuAssertTrue(tc, lr == 0);
3321
3322 s = SH_ALLOC(64); sl_strlcpy(s, str6, 64); p = s; lo = strlen(s); lr = lo;
3323 q = sh_files_C_dequote(s, &lr);
3324 CuAssertTrue(tc, q == NULL);
3325 CuAssertTrue(tc, lr == 0);
3326
3327 return;
3328#else
3329 (void) tc; /* fix compiler warning */
3330 return;
3331#endif
3332}
3333#endif
3334
Note: See TracBrowser for help on using the repository browser.