source: trunk/src/sh_files.c@ 546

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

Fix for ticket #434 (option to init for alternative root fs).

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