source: trunk/src/sh_files.c@ 494

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

Fix for tickets #386 (silent check) and #387 (linux audit support).

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