source: trunk/src/sh_files.c@ 526

Last change on this file since 526 was 516, checked in by katerina, 8 years ago

Fix for ticket #409 and #410 (unprivileged suidcheck and gcc 6.2 compiler warnings).

File size: 82.0 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 volatile 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 char * type_name;
1178 int class;
1179 unsigned long check_flags;
1180 int rdepth;
1181 short type;
1182 /* struct dirstack_entry * next; */
1183} sh_globstack_t;
1184
1185static zAVLTree * zglobList = NULL;
1186
1187zAVLKey zglobstack_key (void const * arg)
1188{
1189 const sh_globstack_t * sa = (const sh_globstack_t *) arg;
1190 return (zAVLKey) sa->type_name;
1191}
1192
1193
1194static int sh_files_pushglob (int class, int type, const char * p, int rdepth,
1195 unsigned long check_flags_in, int flag)
1196{
1197 int globstatus = -1;
1198 unsigned int gloop;
1199 glob_t pglob;
1200
1201 volatile int count = 0;
1202 volatile unsigned long check_flags = (flag == 0) ? sh_files_maskof(class) : check_flags_in;
1203
1204 SL_ENTER(_("sh_files_pushglob"));
1205
1206 pglob.gl_offs = 0;
1207 globstatus = glob (p, 0, sh_files_globerr, &pglob);
1208
1209 if (sh.flag.checkSum != SH_CHECK_INIT)
1210 {
1211 sh_globstack_t * new_item_ptr;
1212 char * fileName;
1213 char * typeName;
1214 int ret;
1215
1216 SH_MUTEX_TRYLOCK(mutex_zfiles);
1217 fileName = sh_util_strdup (p);
1218 typeName = sh_util_strconcat ((type == SH_LIST_FILE) ? "F" : "D", p, NULL);
1219
1220 new_item_ptr = (sh_globstack_t *) SH_ALLOC (sizeof(sh_globstack_t));
1221
1222 new_item_ptr->name = fileName;
1223 new_item_ptr->type_name = typeName;
1224 new_item_ptr->class = class;
1225 new_item_ptr->check_flags = check_flags;
1226 new_item_ptr->rdepth = rdepth;
1227 new_item_ptr->type = type;
1228
1229 if (zglobList == NULL)
1230 {
1231 zglobList = zAVLAllocTree (zglobstack_key, zAVL_KEY_STRING);
1232 if (zglobList == NULL)
1233 {
1234 (void) safe_logger (0, 0, NULL);
1235 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1236 }
1237 }
1238
1239 ret = zAVLInsert (zglobList, new_item_ptr);
1240
1241 if (ret != 0) /* already in list */
1242 {
1243 SH_FREE(fileName);
1244 SH_FREE(typeName);
1245 SH_FREE(new_item_ptr);
1246 }
1247 SH_MUTEX_TRYLOCK_UNLOCK(mutex_zfiles);
1248 }
1249
1250
1251 if (globstatus == 0 && pglob.gl_pathc > 0)
1252 {
1253 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
1254 {
1255 if (type == SH_LIST_FILE)
1256 {
1257 count += sh_files_push_file_int (class, pglob.gl_pathv[gloop],
1258 sl_strlen(pglob.gl_pathv[gloop]), check_flags);
1259 }
1260 else
1261 {
1262 which_dirList = type;
1263
1264 count += sh_files_push_dir_int (class, pglob.gl_pathv[gloop],
1265 sl_strlen(pglob.gl_pathv[gloop]), rdepth, check_flags);
1266 }
1267 }
1268 }
1269 else
1270 {
1271 char * tmp = sh_util_safe_name (p);
1272
1273 if (pglob.gl_pathc == 0
1274#ifdef GLOB_NOMATCH
1275 || globstatus == GLOB_NOMATCH
1276#endif
1277 )
1278 sh_error_handle ((sh.flag.started != S_TRUE) ? SH_ERR_ERR : SH_ERR_NOTICE,
1279 FIL__, __LINE__,
1280 globstatus, MSG_FI_GLOB,
1281 _("No matches found"), tmp);
1282#ifdef GLOB_NOSPACE
1283 else if (globstatus == GLOB_NOSPACE)
1284 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1285 globstatus, MSG_FI_GLOB,
1286 _("Out of memory"), tmp);
1287#endif
1288#ifdef GLOB_ABORTED
1289 else if (globstatus == GLOB_ABORTED)
1290 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1291 globstatus, MSG_FI_GLOB,
1292 _("Read error"), tmp);
1293#endif
1294 else
1295 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1296 globstatus, MSG_FI_GLOB,
1297 _("Unknown error"), tmp);
1298
1299 SH_FREE(tmp);
1300
1301 }
1302
1303 globfree(&pglob);
1304 SL_RETURN(count, _("sh_files_pushglob"));
1305 return count;
1306}
1307
1308void sh_files_check_globFilePatterns()
1309{
1310 sh_globstack_t * testPattern;
1311 zAVLCursor cursor;
1312
1313 SL_ENTER(_("sh_files_check_globPatterns"));
1314
1315 SH_MUTEX_LOCK(mutex_zglob);
1316 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
1317 testPattern;
1318 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
1319 {
1320 if (testPattern->type == SH_LIST_FILE)
1321 {
1322 sh_files_pushglob(testPattern->class, testPattern->type,
1323 testPattern->name, testPattern->rdepth,
1324 testPattern->check_flags, 1);
1325 }
1326 }
1327 SH_MUTEX_UNLOCK(mutex_zglob);
1328 SL_RET0(_("sh_files_check_globPatterns"));
1329}
1330
1331void sh_files_check_globPatterns()
1332{
1333 sh_globstack_t * testPattern;
1334 zAVLCursor cursor;
1335
1336 SL_ENTER(_("sh_files_check_globPatterns"));
1337
1338 SH_MUTEX_LOCK(mutex_zglob);
1339 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
1340 testPattern;
1341 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
1342 {
1343 sh_files_pushglob(testPattern->class, testPattern->type,
1344 testPattern->name, testPattern->rdepth,
1345 testPattern->check_flags, 1);
1346 }
1347 SH_MUTEX_UNLOCK(mutex_zglob);
1348 SL_RET0(_("sh_files_check_globPatterns"));
1349}
1350
1351/* the destructor
1352 */
1353void free_globstack (void * inptr)
1354{
1355 sh_globstack_t * here;
1356
1357 SL_ENTER(_("free_globstack"));
1358 if (inptr == NULL)
1359 SL_RET0(_("free_globstack"));
1360 else
1361 here = (sh_globstack_t *) inptr;
1362
1363 if (here->name != NULL)
1364 SH_FREE(here->name);
1365 if (here->type_name != NULL)
1366 SH_FREE(here->type_name);
1367 SH_FREE(here);
1368 SL_RET0(_("free_globstack"));
1369}
1370
1371int sh_files_delglobstack ()
1372{
1373 SL_ENTER(_("sh_files_delglobstack"));
1374
1375 SH_MUTEX_LOCK(mutex_zglob);
1376 zAVLFreeTree (zglobList, free_globstack);
1377 zglobList = NULL;
1378 SH_MUTEX_UNLOCK(mutex_zglob);
1379
1380 SL_RETURN(0, _("sh_files_delglobstack"));
1381}
1382
1383
1384#else
1385void sh_files_check_globPatterns()
1386{
1387 return;
1388}
1389int sh_files_delglobstack ()
1390{
1391 return 0;
1392}
1393#endif
1394
1395static int sh_files_pushfile (int class, const char * str_s)
1396{
1397 size_t len;
1398 char * tmp;
1399 char * p;
1400
1401 static int reject = 0;
1402
1403 SL_ENTER(_("sh_files_pushfile"));
1404
1405 if (reject == 1)
1406 SL_RETURN((-1),_("sh_files_pushfile"));
1407
1408 /* if we push a filename from the command line, make sure it
1409 * is the only one -- and will stay the only one
1410 */
1411 if (sh.flag.opts == S_TRUE)
1412 {
1413 sh_files_delfilestack ();
1414 sh_files_deldirstack ();
1415 sh_files_delglobstack ();
1416 reject = 1;
1417 }
1418
1419 p = sh_files_parse_input(str_s, &len);
1420 if (!p || len == 0)
1421 SL_RETURN((-1), _("sh_files_pushfile"));
1422
1423 if (len >= PATH_MAX)
1424 {
1425 /* Name too long
1426 */
1427 tmp = sh_util_safe_name (p);
1428 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1429 tmp);
1430 SH_FREE(tmp);
1431 SL_RETURN((-1),_("sh_files_pushfile"));
1432 }
1433 else if (p[0] != '/')
1434 {
1435 /* Not an absolute path
1436 */
1437 tmp = sh_util_safe_name (p);
1438 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1439 tmp);
1440 SH_FREE(tmp);
1441 SL_RETURN((-1),_("sh_files_pushfile"));
1442 }
1443 else
1444 {
1445 /* remove a terminating '/', take care of the
1446 * special case of the root directory.
1447 */
1448 if (p[len-1] == '/' && len > 1)
1449 {
1450 p[len-1] = '\0';
1451 --len;
1452 }
1453 }
1454
1455#ifdef HAVE_GLOB_H
1456 if (0 == sh_files_has_metachar(p))
1457 {
1458 sh_files_push_file_int (class, p, len, sh_files_maskof(class));
1459 }
1460 else
1461 {
1462 sh_files_pushglob (class, SH_LIST_FILE, p, 0, 0, 0);
1463 }
1464
1465#else
1466 sh_files_push_file_int (class, p, len, sh_files_maskof(class));
1467#endif
1468
1469 SH_FREE(p);
1470 SL_RETURN((0),_("sh_files_pushfile"));
1471}
1472
1473
1474/* ------ directories ----- */
1475
1476int sh_files_is_allignore_int (char * str, zAVLTree * tree)
1477{
1478 dirstack_t * ptr;
1479
1480 SL_ENTER(_("sh_files_is_allignore"));
1481
1482 if (tree)
1483 {
1484 ptr = zAVLSearch(tree, str);
1485 if (ptr)
1486 {
1487 if (ptr->class == SH_LEVEL_ALLIGNORE)
1488 SL_RETURN( 1, _("sh_files_is_allignore"));
1489 else
1490 SL_RETURN( 0, _("sh_files_is_allignore"));
1491 }
1492 }
1493 SL_RETURN( 0, _("sh_files_is_allignore"));
1494}
1495
1496int sh_files_is_allignore (char * str)
1497{
1498 int retval = 0;
1499
1500 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1501 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1502 retval = sh_files_is_allignore_int(str, zdirListOne);
1503
1504 if (NULL != zdirListTwo && retval == 0)
1505 {
1506 retval = sh_files_is_allignore_int(str, zdirListTwo);
1507 }
1508 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1509 return retval;
1510}
1511
1512void * sh_dummy_1493_ptr;
1513
1514unsigned long sh_dirs_chk (int which)
1515{
1516 zAVLTree * tree;
1517 zAVLCursor cursor;
1518 dirstack_t * ptr;
1519 dirstack_t * dst_ptr;
1520 int status;
1521 int tmp_reported;
1522 volatile int filetype = SH_FILE_UNKNOWN;
1523 volatile unsigned long dcount = 0;
1524 char * tmp;
1525
1526 SL_ENTER(_("sh_dirs_chk"));
1527
1528 sh_dummy_1493_ptr = (void *) &ptr;
1529
1530 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1531 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1532 if (which == 1)
1533 tree = zdirListOne;
1534 else
1535 tree = zdirListTwo;
1536
1537 for (ptr = (dirstack_t *) zAVLFirst(&cursor, tree); ptr;
1538 ptr = (dirstack_t *) zAVLNext(&cursor))
1539 {
1540 if (sig_urgent > 0) {
1541 goto out;
1542 }
1543
1544 if (ptr->checked == S_FALSE)
1545 {
1546 SH_MUTEX_LOCK(mutex_zfiles);
1547 /* 28 Aug 2001 check the top level directory
1548 */
1549 status = S_FALSE;
1550 dst_ptr = zAVLSearch(zfileList, ptr->name);
1551 if (dst_ptr)
1552 {
1553 if (dst_ptr->checked == S_FALSE)
1554 {
1555 BREAKEXIT(sh_files_filecheck);
1556 tmp_reported = dst_ptr->is_reported;
1557 filetype = sh_files_filecheck (dst_ptr->class, dst_ptr->check_flags,
1558 ptr->name,
1559 NULL, &tmp_reported, 0);
1560 dst_ptr->is_reported = tmp_reported;
1561 (void) handle_filecheck_ret(dst_ptr, NULL, filetype);
1562
1563 dst_ptr->checked = S_TRUE;
1564 status = S_TRUE;
1565 }
1566 else
1567 {
1568 status = S_TRUE;
1569 }
1570 }
1571 SH_MUTEX_UNLOCK(mutex_zfiles);
1572
1573 if (status == S_FALSE)
1574 {
1575 tmp_reported = ptr->is_reported;
1576 filetype = sh_files_filecheck (ptr->class, ptr->check_flags,
1577 ptr->name, NULL, &tmp_reported, 0);
1578 ptr->is_reported = tmp_reported;
1579 (void) handle_filecheck_ret(ptr, NULL, filetype);
1580 }
1581
1582 BREAKEXIT(sh_files_checkdir);
1583 status = sh_files_checkdir (ptr->class, ptr->check_flags,
1584 ptr->rdepth, ptr->name,
1585 ptr->name);
1586
1587 if (status < 0 && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
1588 {
1589 /* directory is missing
1590 */
1591 if (S_FALSE == sh_ignore_chk_del(ptr->name))
1592 {
1593 if (0 != hashreport_missing(ptr->name,
1594 (ptr->class == SH_LEVEL_ALLIGNORE) ?
1595 ShDFLevel[ptr->class] :
1596 ShDFLevel[SH_ERR_T_DIR])) {
1597 tmp = sh_util_safe_name (ptr->name);
1598 if (!sh_global_check_silent)
1599 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1600 ShDFLevel[ptr->class] :
1601 ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__,
1602 0, MSG_FI_MISS, tmp);
1603 ++sh.statistics.files_report;
1604 SH_FREE(tmp);
1605 }
1606 }
1607 if (sh.flag.reportonce == S_TRUE)
1608 SET_SH_FFLAG_REPORTED(ptr->is_reported);
1609 }
1610 else
1611 {
1612 /* exists (status >= 0), but was missing (reported == TRUE)
1613 */
1614 if (status >= 0 && SH_FFLAG_REPORTED_SET(ptr->is_reported))
1615 {
1616 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
1617 sh_hash_clear_flag(ptr->name, SH_FFLAG_ENOENT);
1618#if 0
1619 /* obsoleted (really?) by the mandatory sh_files_filecheck()
1620 * above, which will catch missing directories anyway
1621 */
1622 tmp = sh_util_safe_name (ptr->name);
1623 if (!sh_global_check_silent)
1624 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1625 ShDFLevel[ptr->class] :
1626 ShDFLevel[SH_ERR_T_DIR],
1627 FIL__, __LINE__, 0, MSG_FI_ADD,
1628 tmp);
1629 ++sh.statistics.files_report;
1630 SH_FREE(tmp);
1631#endif
1632 }
1633 else if (status == SH_FILE_UNKNOWN)
1634 {
1635 /* catchall
1636 */
1637 tmp = sh_util_safe_name (ptr->name);
1638 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
1639 MSG_FI_FAIL,
1640 tmp);
1641 SH_FREE(tmp);
1642 if (sh.flag.checkSum != SH_CHECK_INIT)
1643 sh_hash_set_visited_true(ptr->name);
1644 }
1645
1646 ++dcount;
1647 }
1648 ptr->checked = S_TRUE;
1649 ptr->childs_checked = S_TRUE;
1650 }
1651
1652 if (sig_urgent > 0) {
1653 goto out;
1654 }
1655
1656 }
1657 out:
1658 ; /* 'label at end of compound statement' */
1659 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1660
1661 SL_RETURN(dcount, _("sh_dirs_chk"));
1662}
1663
1664int sh_files_pushdir_prelink (const char * str_s)
1665{
1666 return (sh_files_pushdir (SH_LEVEL_PRELINK, str_s));
1667}
1668
1669int sh_files_pushdir_user0 (const char * str_s)
1670{
1671 return (sh_files_pushdir (SH_LEVEL_USER0, str_s));
1672}
1673
1674int sh_files_pushdir_user1 (const char * str_s)
1675{
1676 return (sh_files_pushdir (SH_LEVEL_USER1, str_s));
1677}
1678
1679int sh_files_pushdir_user2 (const char * str_s)
1680{
1681 return (sh_files_pushdir (SH_LEVEL_USER2, str_s));
1682}
1683
1684int sh_files_pushdir_user3 (const char * str_s)
1685{
1686 return (sh_files_pushdir (SH_LEVEL_USER3, str_s));
1687}
1688
1689int sh_files_pushdir_user4 (const char * str_s)
1690{
1691 return (sh_files_pushdir (SH_LEVEL_USER4, str_s));
1692}
1693
1694int sh_files_pushdir_attr (const char * str_s)
1695{
1696 return (sh_files_pushdir (SH_LEVEL_ATTRIBUTES, str_s));
1697}
1698
1699int sh_files_pushdir_ro (const char * str_s)
1700{
1701 return (sh_files_pushdir (SH_LEVEL_READONLY, str_s));
1702}
1703
1704int sh_files_pushdir_log (const char * str_s)
1705{
1706 return (sh_files_pushdir (SH_LEVEL_LOGFILES, str_s));
1707}
1708
1709int sh_files_pushdir_glog (const char * str_s)
1710{
1711 return (sh_files_pushdir (SH_LEVEL_LOGGROW, str_s));
1712}
1713
1714int sh_files_pushdir_noig (const char * str_s)
1715{
1716 return (sh_files_pushdir (SH_LEVEL_NOIGNORE, str_s));
1717}
1718
1719int sh_files_pushdir_allig (const char * str_s)
1720{
1721 return (sh_files_pushdir (SH_LEVEL_ALLIGNORE, str_s));
1722}
1723
1724int set_dirList (int which)
1725{
1726 if (which == 2)
1727 which_dirList = SH_LIST_DIR2;
1728 else
1729 which_dirList = SH_LIST_DIR1;
1730 return 0;
1731}
1732
1733int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_flags)
1734{
1735 zAVLTree * tree;
1736 dirstack_t * new_item_ptr;
1737 char * dirName;
1738 int ret;
1739
1740 SL_ENTER(_("sh_files_push_dir_int"));
1741
1742 dirName = SH_ALLOC(len+1);
1743 sl_strlcpy(dirName, tail, len+1);
1744
1745 new_item_ptr = (dirstack_t * ) SH_ALLOC (sizeof(dirstack_t));
1746
1747 new_item_ptr->name = dirName;
1748 new_item_ptr->class = class;
1749 new_item_ptr->check_flags = check_flags;
1750 new_item_ptr->rdepth = rdepth;
1751 new_item_ptr->checked = S_FALSE;
1752 new_item_ptr->is_reported = 0;
1753 new_item_ptr->childs_checked = S_FALSE;
1754
1755 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1756 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1757 if (which_dirList == SH_LIST_DIR1)
1758 {
1759 tree = zdirListOne;
1760 }
1761 else
1762 {
1763 tree = zdirListTwo;
1764 }
1765
1766 if (tree == NULL)
1767 {
1768 tree = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
1769 if (tree == NULL)
1770 {
1771 (void) safe_logger (0, 0, NULL);
1772 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1773 }
1774 if (which_dirList == SH_LIST_DIR1)
1775 zdirListOne = tree;
1776 else
1777 zdirListTwo = tree;
1778 }
1779
1780 ret = zAVLInsert (tree, new_item_ptr);
1781 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1782
1783 if (-1 == ret)
1784 {
1785 (void) safe_logger (0, 0, NULL);
1786 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1787 }
1788 if (3 == ret)
1789 {
1790 if (sh.flag.started != S_TRUE)
1791 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
1792 dirName);
1793 SH_FREE(dirName);
1794 SH_FREE(new_item_ptr);
1795 new_item_ptr = NULL;
1796 }
1797 else
1798 {
1799 if (MODI_AUDIT_ENABLED(check_flags))
1800 {
1801 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1802 _("Setting audit watch"),
1803 _("sh_files_push_file_int"), tail);
1804 sh_audit_mark(tail);
1805 }
1806 }
1807 SL_RETURN(0, _("sh_files_push_dir_int"));
1808}
1809
1810static int sh_files_pushdir (int class, const char * str_s)
1811{
1812 char * tmp;
1813 size_t len;
1814 int rdepth = 0;
1815 char * tail = NULL;
1816 char * p;
1817
1818 SL_ENTER(_("sh_files_pushdir"));
1819
1820 if (sh.flag.opts == S_TRUE) {
1821 sh_files_delfilestack ();
1822 sh_files_deldirstack ();
1823 sh_files_delglobstack ();
1824 }
1825
1826 p = sh_files_parse_input(str_s, &len);
1827 if (!p || len == 0)
1828 SL_RETURN((-1),_("sh_files_pushdir"));
1829
1830 if (p[0] != '/')
1831 {
1832 rdepth = strtol(p, &tail, 10);
1833 if (tail == p)
1834 {
1835 SH_FREE(p);
1836 SL_RETURN((-1), _("sh_files_pushdir"));
1837 }
1838 }
1839 else
1840 tail = p;
1841
1842
1843 if (tail == p)
1844 {
1845 /* Setting to an invalid number will force MaxRecursionLevel,
1846 * see sh_files_setrec_int()
1847 */
1848 rdepth = (-2);
1849 }
1850 else if ( (rdepth < (-1) || rdepth > 99) ||
1851 ((rdepth == (-1)) && (class != SH_LEVEL_ALLIGNORE)) )
1852 {
1853 SH_FREE(p);
1854 SL_RETURN((-1), _("sh_files_pushdir"));
1855 }
1856
1857 len = sl_strlen(tail);
1858
1859 if (len >= PATH_MAX)
1860 {
1861 tmp = sh_util_safe_name (tail);
1862 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1863 tmp);
1864 SH_FREE(tmp);
1865 SH_FREE(p);
1866 SL_RETURN((-1), _("sh_files_pushdir"));
1867 }
1868 else if (len < 1)
1869 {
1870 SH_FREE(p);
1871 SL_RETURN((-1), _("sh_files_pushdir"));
1872 }
1873 else if (tail[0] != '/')
1874 {
1875 tmp = sh_util_safe_name (tail);
1876 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1877 tmp);
1878 SH_FREE(tmp);
1879 SH_FREE(p);
1880 SL_RETURN((-1), _("sh_files_pushdir"));
1881 }
1882 else
1883 {
1884 if (tail[len-1] == '/' && len > 1)
1885 {
1886 tail[len-1] = '\0';
1887 --len;
1888 }
1889 }
1890
1891#ifdef HAVE_GLOB_H
1892 if (0 == sh_files_has_metachar(tail))
1893 {
1894 sh_files_push_dir_int (class, tail, len, rdepth, sh_files_maskof(class));
1895 }
1896 else
1897 {
1898 sh_files_pushglob (class, which_dirList, tail, rdepth, 0, 0);
1899 }
1900#else
1901 sh_files_push_dir_int (class, tail, len, rdepth, sh_files_maskof(class));
1902#endif
1903
1904 SH_FREE(p);
1905 SL_RETURN((0), _("sh_files_pushdir"));
1906}
1907
1908/**
1909struct sh_dirent {
1910 char * sh_d_name;
1911 struct sh_dirent * next;
1912};
1913**/
1914
1915void kill_sh_dirlist (struct sh_dirent * dirlist)
1916{
1917 struct sh_dirent * this;
1918
1919 while (dirlist)
1920 {
1921 this = dirlist->next;
1922 SH_FREE(dirlist->sh_d_name);
1923 SH_FREE(dirlist);
1924 dirlist = this;
1925 }
1926 return;
1927}
1928
1929/* -- add an entry to a directory listing
1930 */
1931struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry,
1932 struct sh_dirent * dirlist)
1933{
1934 struct sh_dirent * this;
1935 size_t len;
1936
1937 if (thisEntry == NULL)
1938 return dirlist;
1939
1940 len = sl_strlen(thisEntry->d_name);
1941 if (len == 0)
1942 return dirlist;
1943 ++len;
1944
1945 this = SH_ALLOC(sizeof(struct sh_dirent));
1946 if (!this)
1947 return dirlist;
1948
1949 this->sh_d_name = SH_ALLOC(len);
1950 sl_strlcpy(this->sh_d_name, thisEntry->d_name, len);
1951
1952 this->next = dirlist;
1953 return this;
1954}
1955
1956static int sh_check_hardlinks = S_TRUE;
1957
1958/* Simply sets our boolean as to whether this check is active
1959 */
1960int sh_files_check_hardlinks (const char * opt)
1961{
1962 int i;
1963 SL_ENTER(_("sh_files_check_hardlinks"));
1964 i = sh_util_flagval(opt, &sh_check_hardlinks);
1965 SL_RETURN(i, _("sh_files_check_hardlinks"));
1966}
1967
1968struct sh_hle_struct {
1969 long offset;
1970 char * path;
1971 struct sh_hle_struct * next;
1972};
1973
1974static struct sh_hle_struct * sh_hl_exc = NULL;
1975
1976int sh_files_hle_reg (const char * str)
1977{
1978 long offset;
1979 size_t len;
1980 char * path;
1981
1982 struct sh_hle_struct * tmp = sh_hl_exc;
1983
1984 SL_ENTER(_("sh_files_hle_reg"));
1985
1986 /* Free the linked list if called with NULL argument
1987 */
1988 if (str == NULL)
1989 {
1990 while (tmp)
1991 {
1992 sh_hl_exc = tmp->next;
1993 SH_FREE(tmp->path);
1994 SH_FREE(tmp);
1995 tmp = sh_hl_exc;
1996 }
1997 sh_hl_exc = NULL;
1998 SL_RETURN(0, _("sh_files_hle_reg"));
1999 }
2000
2001 /* We expect 'offset:/path'
2002 */
2003 offset = strtol(str, &path, 0);
2004 if ((path == NULL) || (*path == '\0') || (*path != ':') || (path[1] != '/'))
2005 {
2006 SL_RETURN(-1, _("sh_files_hle_reg"));
2007 }
2008 ++path;
2009 len = 1 + sl_strlen(path);
2010
2011 tmp = SH_ALLOC(sizeof(struct sh_hle_struct));
2012 tmp->path = SH_ALLOC(len);
2013 sl_strlcpy (tmp->path, path, len);
2014 tmp->offset = offset;
2015 tmp->next = sh_hl_exc;
2016 sh_hl_exc = tmp;
2017
2018 SL_RETURN(0, _("sh_files_hle_reg"));
2019}
2020
2021#if !defined(HOST_IS_DARWIN)
2022static int sh_files_hle_test (int offset, char * path)
2023{
2024 struct sh_hle_struct * tmp = sh_hl_exc;
2025
2026 SL_ENTER(_("sh_files_hle_reg"));
2027
2028 while(tmp)
2029 {
2030 if ((offset == tmp->offset) && (0 == strcmp(path, tmp->path)))
2031 {
2032 SL_RETURN(0, _("sh_files_hle_test"));
2033 }
2034 tmp = tmp->next;
2035 }
2036#ifdef HAVE_FNMATCH_H
2037 if ( (offset == 1) && (0 == fnmatch(_("/run/user/*"), path, FNM_PATHNAME)) )
2038 {
2039 /* gvfs directory in /run/user/username/ */
2040 SL_RETURN(0, _("sh_files_hle_test"));
2041 }
2042#endif
2043
2044 SL_RETURN(-1, _("sh_files_hle_test"));
2045}
2046#endif
2047
2048void * sh_dummy_dirlist;
2049void * sh_dummy_tmpcat;
2050
2051/* -- Check a single directory and its content. Does not
2052 * check the directory inode itself.
2053 */
2054int sh_files_checkdir (int iclass, unsigned long check_flags,
2055 int idepth, char * iname,
2056 char * relativeName)
2057{
2058 struct sh_dirent * dirlist;
2059 struct sh_dirent * dirlist_orig;
2060
2061 DIR * thisDir = NULL;
2062 struct dirent * thisEntry;
2063 int status;
2064 int dummy = S_FALSE;
2065 dir_type * theDir;
2066 ShFileType checkit;
2067 static unsigned int state = 1;
2068
2069 file_type * theFile;
2070 char * tmpname;
2071 char * tmpcat;
2072 char errbuf[SH_ERRBUF_SIZE];
2073
2074 int rdepth = 0;
2075 int class = 0;
2076 volatile int rdepth_next;
2077 volatile int class_next;
2078 volatile int file_class_next;
2079 volatile unsigned long check_flags_next;
2080 volatile unsigned long file_check_flags_next;
2081
2082 volatile int checked_flag = S_FALSE;
2083 volatile int cchecked_flag = S_FALSE;
2084
2085 dirstack_t * dst_ptr;
2086 dirstack_t * tmp_ptr;
2087
2088 int hardlink_num = 0;
2089#if !defined(HOST_IS_DARWIN)
2090 size_t len;
2091#endif
2092
2093 SL_ENTER(_("sh_files_checkdir"));
2094
2095 if (sig_urgent > 0) {
2096 SL_RETURN((0), _("sh_files_checkdir"));
2097 }
2098
2099 if (iname == NULL || idepth < (-1))
2100 SL_RETURN((-1), _("sh_files_checkdir"));
2101
2102 if (idepth < 0)
2103 {
2104 /* hash_remove_tree (iname); */
2105 SL_RETURN((0), _("sh_files_checkdir"));
2106 }
2107
2108 rdepth = idepth;
2109 class = iclass;
2110
2111 tmpname = sh_util_safe_name (iname);
2112
2113 /* ---- check for obscure name ----
2114 */
2115 if (iclass != SH_LEVEL_ALLIGNORE)
2116 {
2117 sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], iname, S_TRUE);
2118 }
2119
2120 if (flag_err_info == S_TRUE)
2121 {
2122 char pstr[32];
2123
2124 sl_strlcpy(pstr, sh_hash_getpolicy(iclass), sizeof(pstr));
2125 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, pstr, tmpname);
2126 }
2127
2128 /* ---- check input ----
2129 */
2130 if ( sl_strlen(iname) >= PATH_MAX)
2131 {
2132 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2133 MSG_FI_2LONG,
2134 tmpname);
2135 SH_FREE(tmpname);
2136 SL_RETURN((-1), _("sh_files_checkdir"));
2137 }
2138
2139 /* ---- check for absolute path ---- */
2140 if ( iname[0] != '/')
2141 {
2142 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2143 MSG_FI_NOPATH,
2144 tmpname);
2145 SH_FREE(tmpname);
2146 SL_RETURN((-1), _("sh_files_checkdir"));
2147 }
2148
2149 /* ---- stat the directory ----
2150 */
2151 theFile = SH_ALLOC(sizeof(file_type));
2152 sl_strlcpy (theFile->fullpath, iname, PATH_MAX);
2153 theFile->attr_string = NULL;
2154 theFile->link_path = NULL;
2155 theFile->check_flags = check_flags;
2156
2157 (void) relativeName;
2158 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_DIR],
2159 iname,
2160 theFile, NULL, iclass);
2161
2162 if ((sig_termfast == 1) || (sig_terminate == 1))
2163 {
2164 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2165 if (theFile->link_path) SH_FREE(theFile->link_path);
2166 SH_FREE(theFile);
2167 SH_FREE(tmpname);
2168 SL_RETURN((0), _("sh_files_checkdir"));
2169 }
2170
2171 if (status == -1)
2172 {
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 (theFile->c_mode[0] != 'd')
2181 {
2182 if (!sh_global_check_silent)
2183 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2184 MSG_FI_NODIR,
2185 tmpname);
2186 ++sh.statistics.files_nodir;
2187 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2188 if (theFile->link_path) SH_FREE(theFile->link_path);
2189 SH_FREE(theFile);
2190 SH_FREE(tmpname);
2191 SL_RETURN((-1), _("sh_files_checkdir"));
2192 }
2193
2194 if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
2195 {
2196 sh_inotify_add_watch_later(iname, &sh_file_watches, &status,
2197 iclass, check_flags, SH_INOTIFY_DIR, idepth);
2198 }
2199
2200 hardlink_num = theFile->hardlinks;
2201
2202 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2203 if (theFile->link_path) SH_FREE(theFile->link_path);
2204 SH_FREE(theFile);
2205
2206 /* ---- open directory for reading ----
2207 *
2208 * opendir() will fail with ENOTDIR if the path has been changed
2209 * to a non-directory in between lstat() and opendir().
2210 */
2211 thisDir = opendir (iname);
2212
2213 if (thisDir == NULL)
2214 {
2215 status = errno;
2216 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2217 MSG_E_OPENDIR,
2218 sh_error_message (status, errbuf, sizeof(errbuf)), tmpname);
2219 SH_FREE(tmpname);
2220 SL_RETURN((-1), _("sh_files_checkdir"));
2221 }
2222
2223 theDir = SH_ALLOC(sizeof(dir_type));
2224
2225 theDir->NumRegular = 0;
2226 theDir->NumDirs = 0;
2227 theDir->NumSymlinks = 0;
2228 theDir->NumFifos = 0;
2229 theDir->NumSockets = 0;
2230 theDir->NumCDev = 0;
2231 theDir->NumBDev = 0;
2232 theDir->NumDoor = 0;
2233 theDir->NumPort = 0;
2234 theDir->NumAll = 0;
2235 theDir->TotalBytes = 0;
2236 sl_strlcpy (theDir->DirPath, iname, PATH_MAX);
2237
2238
2239 sh_dummy_dirlist = (void *) &dirlist;
2240 sh_dummy_tmpcat = (void *) &tmpcat;
2241
2242 /* ---- read ----
2243 */
2244 SH_MUTEX_LOCK(mutex_readdir);
2245
2246 dirlist = NULL;
2247 dirlist_orig = NULL;
2248
2249 do {
2250 thisEntry = readdir (thisDir);
2251 if (thisEntry != NULL)
2252 {
2253 ++theDir->NumAll;
2254 if (sl_strcmp (thisEntry->d_name, ".") == 0)
2255 {
2256 ++theDir->NumDirs;
2257 continue;
2258 }
2259 if (sl_strcmp (thisEntry->d_name, "..") == 0)
2260 {
2261 ++theDir->NumDirs;
2262 continue;
2263 }
2264 dirlist = addto_sh_dirlist (thisEntry, dirlist);
2265 }
2266 } while (thisEntry != NULL);
2267
2268 SH_MUTEX_UNLOCK(mutex_readdir);
2269
2270 closedir (thisDir);
2271
2272 ++sh.statistics.dirs_checked;
2273
2274 dirlist_orig = dirlist;
2275
2276 do {
2277
2278 /* If the directory is empty, dirlist = NULL
2279 */
2280 if (!dirlist)
2281 break;
2282
2283 if (sig_termfast == 1)
2284 {
2285 SH_FREE(theDir);
2286 SH_FREE(tmpname);
2287 SL_RETURN((0), _("sh_files_checkdir"));
2288 }
2289
2290 BREAKEXIT(sh_derr);
2291
2292#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
2293 if (0 == (rand_r(&state) % 5)) (void) sh_derr();
2294#else
2295 if (0 == state * (rand() % 5)) (void) sh_derr();
2296#endif
2297
2298 /* ---- Check the file. ----
2299 */
2300 tmpcat = SH_ALLOC(PATH_MAX);
2301 sl_strlcpy(tmpcat, iname, PATH_MAX);
2302 if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/')
2303 sl_strlcat(tmpcat, "/", PATH_MAX);
2304 sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX);
2305
2306 rdepth_next = rdepth - 1;
2307 class_next = class;
2308 check_flags_next = check_flags;
2309 file_class_next = class;
2310 file_check_flags_next = check_flags;
2311 checked_flag = -1;
2312 cchecked_flag = -1;
2313
2314 /* Wed Aug 24 2005 compare against dirListOne, dirListTwo
2315 * this fixes the problem that the directory special file
2316 * is checked with the policy of the parent directory
2317 */
2318 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2319 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2320 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2321
2322 if (dst_ptr)
2323 {
2324 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2325 * this fixes the problem that a policy for the directory
2326 * inode erroneously becomes a policy for the directory itself.
2327 */
2328 file_class_next = dst_ptr->class;
2329 file_check_flags_next = dst_ptr->check_flags;
2330 checked_flag = dst_ptr->checked;
2331 cchecked_flag = dst_ptr->childs_checked;
2332 }
2333
2334 if (checked_flag == -1)
2335 {
2336 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, 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 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2351
2352 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2353 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2354
2355 if (dst_ptr)
2356 {
2357 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2358 * this fixes the problem that a policy for the directory
2359 * inode erroneously becomes a policy for the directory itself.
2360 */
2361 file_class_next = dst_ptr->class;
2362 file_check_flags_next = dst_ptr->check_flags;
2363 checked_flag = dst_ptr->checked;
2364 /* not set, hence always FALSE */
2365 /* cchecked_flag = dst_ptr->childs_checked; */
2366
2367 if (checked_flag != S_TRUE)
2368 {
2369 /* -- need to check the file itself --
2370 */
2371 if (sh.flag.reportonce == S_TRUE)
2372 dummy = dst_ptr->is_reported;
2373 }
2374 }
2375 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2376
2377 /* ---- Has been checked already. ----
2378 */
2379 if (checked_flag == S_TRUE && cchecked_flag == S_TRUE)
2380 {
2381 /* Mar 11 2004 get ftype for complete directory count
2382 */
2383 checkit = sh_unix_get_ftype(tmpcat);
2384 if (checkit == SH_FILE_DIRECTORY)
2385 {
2386 ++theDir->NumDirs;
2387 }
2388 SH_FREE(tmpcat);
2389 dirlist = dirlist->next;
2390 continue;
2391 }
2392
2393 /* --- May be true, false, or not found. ---
2394 */
2395 if (checked_flag == S_TRUE)
2396 {
2397 /* -- need only the file type --
2398 */
2399 checkit = sh_unix_get_ftype(tmpcat);
2400 }
2401 else
2402 {
2403 /* -- need to check the file itself --
2404 */
2405 /* -- moved up --
2406 * if (dst_ptr && sh.flag.reportonce == S_TRUE)
2407 * dummy = dst_ptr->is_reported;
2408 */
2409
2410 checkit = sh_files_filecheck (file_class_next, file_check_flags_next,
2411 iname,
2412 dirlist->sh_d_name,
2413 &dummy, 0);
2414
2415
2416 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2417 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2418
2419 if (dst_ptr && checked_flag == S_FALSE)
2420 dst_ptr->checked = S_TRUE;
2421
2422 /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag
2423 */
2424 if (dst_ptr && sh.flag.reportonce == S_TRUE)
2425 dst_ptr->is_reported = dummy;
2426
2427 if (dst_ptr)
2428 dst_ptr->childs_checked = S_TRUE;
2429 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2430 }
2431
2432 if (checkit == SH_FILE_REGULAR)
2433 ++theDir->NumRegular;
2434
2435 else if (checkit == SH_FILE_DIRECTORY)
2436 {
2437 ++theDir->NumDirs;
2438
2439 if (rdepth_next >= 0 && cchecked_flag != S_TRUE)
2440 {
2441 rdepth_next = rdepth - 1;
2442
2443 /* check whether the new directory is in the
2444 * list with a recursion depth already defined
2445 */
2446 checked_flag = -1;
2447 cchecked_flag = -1;
2448
2449 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2450 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2451 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2452
2453 if (tmp_ptr)
2454 {
2455 TPT((0, FIL__, __LINE__,
2456 _("msg=<%s -> recursion depth %d\n>"),
2457 tmp_ptr->name, tmp_ptr->rdepth));
2458 rdepth_next = tmp_ptr->rdepth;
2459 class_next = tmp_ptr->class;
2460 check_flags_next = tmp_ptr->check_flags;
2461 /* 28. Aug 2001 reversed
2462 */
2463 cchecked_flag = tmp_ptr->childs_checked;
2464 checked_flag = tmp_ptr->checked;
2465 }
2466
2467 if (checked_flag == -1)
2468 {
2469 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2470
2471 if (tmp_ptr)
2472 {
2473 TPT((0, FIL__, __LINE__,
2474 _("msg=<%s -> recursion depth %d\n>"),
2475 tmp_ptr->name, tmp_ptr->rdepth));
2476 rdepth_next = tmp_ptr->rdepth;
2477 class_next = tmp_ptr->class;
2478 check_flags_next = tmp_ptr->check_flags;
2479 /* 28. Aug 2001 reversed
2480 */
2481 cchecked_flag = tmp_ptr->childs_checked;
2482 checked_flag = tmp_ptr->checked;
2483 }
2484 }
2485
2486 if (tmp_ptr && cchecked_flag == S_FALSE)
2487 {
2488 tmp_ptr->childs_checked = S_TRUE;
2489 /*
2490 * 04. Feb 2006 avoid double checking
2491 */
2492 tmp_ptr->checked = S_TRUE;
2493 }
2494 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2495
2496 if (cchecked_flag == S_FALSE)
2497 {
2498 sh_files_checkdir (class_next, check_flags_next, rdepth_next,
2499 tmpcat, dirlist->sh_d_name);
2500 /*
2501 tmp_ptr->childs_checked = S_TRUE;
2502 tmp_ptr->checked = S_TRUE;
2503 */
2504 }
2505 else if (checked_flag == -1)
2506 sh_files_checkdir (class_next, check_flags_next, rdepth_next,
2507 tmpcat, dirlist->sh_d_name);
2508
2509 }
2510 }
2511
2512 else if (checkit == SH_FILE_SYMLINK) ++theDir->NumSymlinks;
2513 else if (checkit == SH_FILE_FIFO) ++theDir->NumFifos;
2514 else if (checkit == SH_FILE_SOCKET) ++theDir->NumSockets;
2515 else if (checkit == SH_FILE_CDEV) ++theDir->NumCDev;
2516 else if (checkit == SH_FILE_BDEV) ++theDir->NumBDev;
2517 else if (checkit == SH_FILE_DOOR) ++theDir->NumDoor;
2518 else if (checkit == SH_FILE_PORT) ++theDir->NumPort;
2519
2520 SH_FREE(tmpcat);
2521
2522 if ((sig_termfast == 1) || (sig_terminate == 1))
2523 {
2524 SH_FREE(theDir);
2525 sh_dummy_dirlist = NULL;
2526 SH_FREE(tmpname);
2527 SL_RETURN((0), _("sh_files_checkdir"));
2528 }
2529
2530 dirlist = dirlist->next;
2531
2532 /* -- moved up, only affects zfileList anyway
2533 * if (dst_ptr)
2534 * dst_ptr->childs_checked = S_TRUE;
2535 */
2536
2537 } while (dirlist != NULL);
2538
2539 if (flag_err_info == S_TRUE)
2540 {
2541 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
2542 theDir->NumDirs,
2543 theDir->NumRegular,
2544 theDir->NumSymlinks,
2545 theDir->NumFifos,
2546 theDir->NumSockets,
2547 theDir->NumCDev,
2548 theDir->NumBDev);
2549 }
2550
2551 kill_sh_dirlist (dirlist_orig);
2552
2553#if !defined(HOST_IS_DARWIN)
2554 /*
2555 * Hardlink check; not done on MacOS X because of resource forks
2556 */
2557 if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir->NumDirs))
2558 {
2559 if (0 != sh_files_hle_test(hardlink_num-theDir->NumDirs, iname))
2560 {
2561 len = strlen(tmpname);
2562 if (sl_ok_adds(len, 256))
2563 len += 256;
2564 tmpcat = SH_ALLOC(len);
2565 sl_snprintf(tmpcat, len,
2566 _("%s: subdirectory count (%d) != hardlinks (%d)"),
2567 tmpname, theDir->NumDirs, hardlink_num);
2568 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2569 MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir"));
2570 SH_FREE(tmpcat);
2571 }
2572 }
2573#endif
2574
2575 SH_FREE(tmpname);
2576 SH_FREE(theDir);
2577
2578 sh_dummy_dirlist = NULL;
2579
2580 SL_RETURN((0), _("sh_files_checkdir"));
2581}
2582
2583void sh_files_fixup_mask (int class, unsigned long * check_flags)
2584{
2585 if (class == SH_LEVEL_ALLIGNORE)
2586 MODI_SET((*check_flags), MODI_ALLIGNORE);
2587 sh_tiger_get_mask_hashtype(check_flags);
2588 return;
2589}
2590
2591int get_the_fd (SL_TICKET ticket);
2592
2593static int sh_use_rsrc = S_FALSE;
2594
2595int sh_files_use_rsrc(const char * str)
2596{
2597 return sh_util_flagval(str, &sh_use_rsrc);
2598}
2599
2600static void * sh_dummy_fileName;
2601static void * sh_dummy_tmpname;
2602static void * sh_dummy_tmpdir;
2603
2604ShFileType sh_files_filecheck (int class, unsigned long check_flags,
2605 const char * dirName,
2606 const char * infileName,
2607 int * reported,
2608 int rsrcflag)
2609{
2610 /* 28 Aug 2001 allow NULL fileName
2611 */
2612 char * fullpath;
2613 char fileHash[2*(KEY_LEN + 1)];
2614 int status;
2615 file_type * theFile;
2616 char * tmpdir;
2617 char * tmpname;
2618 const char * fileName;
2619#if !defined(O_NOATIME)
2620 struct utimbuf utime_buf;
2621#endif
2622 static unsigned int state = 1;
2623 char sc;
2624
2625 SL_ENTER(_("sh_files_filecheck"));
2626
2627 fullpath = SH_ALLOC(PATH_MAX);
2628 theFile = SH_ALLOC(sizeof(file_type));
2629
2630 /* Take the address to keep gcc from putting it into a register.
2631 * Avoids the 'clobbered by longjmp' warning.
2632 */
2633 sh_dummy_fileName = (void *) &fileName;
2634 sh_dummy_tmpname = (void *) &tmpname;
2635 sh_dummy_tmpdir = (void *) &tmpdir;
2636
2637 BREAKEXIT(sh_derr);
2638
2639#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
2640 if (0 == (rand_r(&state) % 2)) (void) sh_derr();
2641#else
2642 if (0 == state * (rand() % 2)) (void) sh_derr();
2643#endif
2644
2645 if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0')
2646 && (infileName[0] == '/') && (infileName[1] == '\0'))
2647 {
2648 fileName = NULL;
2649 }
2650 else
2651 {
2652 fileName = infileName;
2653 }
2654
2655 /* fileName may be NULL if this is a directory
2656 */
2657 if (dirName == NULL /* || fileName == NULL */)
2658 {
2659 SH_MUTEX_LOCK(mutex_thread_nolog);
2660 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL);
2661 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2662 SH_FREE(fullpath);
2663 SH_FREE(theFile);
2664 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2665 }
2666
2667 if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) &&
2668 (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME],
2669 fileName, S_FALSE)))
2670 {
2671 if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0'))
2672 {
2673 tmpname = sh_util_safe_name (fileName);
2674 SH_MUTEX_LOCK(mutex_thread_nolog);
2675 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2676 MSG_FI_OBSC2,
2677 "", tmpname);
2678 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2679 SH_FREE(tmpname);
2680 }
2681 else
2682 {
2683 tmpdir = sh_util_safe_name (dirName);
2684 tmpname = sh_util_safe_name (fileName);
2685 SH_MUTEX_LOCK(mutex_thread_nolog);
2686 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2687 MSG_FI_OBSC2,
2688 tmpdir, tmpname);
2689 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2690 SH_FREE(tmpname);
2691 SH_FREE(tmpdir);
2692 }
2693 }
2694
2695 /* sh_files_fullpath accepts NULL fileName
2696 */
2697 if (0 != sh_files_fullpath (dirName, fileName, fullpath))
2698 {
2699 tmpdir = sh_util_safe_name (dirName);
2700 tmpname = sh_util_safe_name (fileName);
2701 SH_MUTEX_LOCK(mutex_thread_nolog);
2702 sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0,
2703 MSG_FI_2LONG2,
2704 tmpdir, tmpname);
2705 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2706 SH_FREE(tmpname);
2707 SH_FREE(tmpdir);
2708 SH_FREE(fullpath);
2709 SH_FREE(theFile);
2710 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2711 }
2712
2713 /* stat the file and determine checksum (if a regular file)
2714 */
2715 sl_strlcpy (theFile->fullpath, fullpath, PATH_MAX);
2716 theFile->check_flags = check_flags /* sh_files_maskof(class) */;
2717 theFile->file_reported = (*reported);
2718 theFile->attr_string = NULL;
2719 theFile->link_path = NULL;
2720
2721 TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"), fullpath));
2722
2723 status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ?
2724 ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE],
2725 fileName,
2726 theFile, fileHash, class);
2727
2728 if (status != 0)
2729 {
2730 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
2731 fullpath, status));
2732 if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
2733 sh_hash_set_visited_true (fullpath);
2734 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2735 if (theFile->link_path) SH_FREE(theFile->link_path);
2736 SH_FREE(fullpath);
2737 SH_FREE(theFile);
2738 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2739 }
2740
2741 if (sig_termfast == 1) {
2742 goto ret_point;
2743 }
2744
2745 /* report
2746 */
2747 if ((flag_err_debug == S_TRUE) && (theFile->c_mode[0] == '-'))
2748 {
2749 tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
2750 SH_MUTEX_LOCK(mutex_thread_nolog);
2751 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM,
2752 fileHash, tmpname);
2753 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2754 SH_FREE(tmpname);
2755 }
2756 ++sh.statistics.files_checked;
2757
2758 if ( sh.flag.checkSum == SH_CHECK_INIT)
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 sh_dbIO_data_write (theFile, fileHash);
2766 }
2767 else if (sh.flag.checkSum == SH_CHECK_CHECK
2768 /* && theFile.c_mode[0] == '-' */
2769 /* && class != SH_LEVEL_ALLIGNORE */
2770 )
2771 {
2772 if (sh.flag.update == S_TRUE)
2773 {
2774 if (class == SH_LEVEL_ALLIGNORE)
2775 MODI_SET(theFile->check_flags, MODI_ALLIGNORE);
2776 if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
2777 MODI_SET(theFile->check_flags, MODI_NOCHECK);
2778 sh_tiger_get_mask_hashtype(&(theFile->check_flags));
2779 }
2780 sh_hash_compdata (class, theFile, fileHash, NULL, -1);
2781 }
2782
2783 (*reported) = theFile->file_reported;
2784
2785 /* reset the access time
2786 */
2787#if !defined(O_NOATIME)
2788 if (class == SH_LEVEL_NOIGNORE && (theFile->check_flags & MODI_ATM) != 0)
2789 {
2790 utime_buf.actime = (time_t) theFile->atime;
2791 utime_buf.modtime = (time_t) theFile->mtime;
2792
2793 retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf);
2794 }
2795#endif
2796
2797#if defined(HOST_IS_DARWIN)
2798 /*
2799 * Check for resource fork
2800 */
2801 if ( (sh_use_rsrc == S_TRUE) && (theFile->c_mode[0] != 'd') && (rsrcflag == 0) )
2802 {
2803 int dummy;
2804 static int rsrc_init = 0;
2805 static char rsrc[17];
2806 char * testpath = SH_ALLOC(PATH_MAX);
2807
2808 if (rsrc_init == 0) {
2809 sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17);
2810 rsrc_init = 1;
2811 }
2812 sl_strlcpy (testpath, fullpath, PATH_MAX);
2813 sl_strlcat (testpath, "/", PATH_MAX);
2814 sl_strlcat (testpath, rsrc, PATH_MAX);
2815
2816 if (sl_strlen(testpath) == (17 + sl_strlen(fullpath)))
2817 {
2818 if (S_TRUE == sh_unix_file_exists (testpath))
2819 {
2820 sh_files_filecheck (class, check_flags, fullpath, rsrc, &dummy, 1);
2821 }
2822 }
2823 SH_FREE(testpath);
2824 }
2825#else
2826 (void) rsrcflag; /* avoid compiler warning */
2827#endif
2828
2829 ret_point:
2830
2831 sc = theFile->c_mode[0];
2832
2833 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2834 if (theFile->link_path) SH_FREE(theFile->link_path);
2835 SH_FREE(fullpath);
2836 SH_FREE(theFile);
2837
2838 switch (sc)
2839 {
2840 case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck"));
2841 case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck"));
2842 case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck"));
2843 case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck"));
2844 case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck"));
2845 case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck"));
2846 case 'D': SL_RETURN(SH_FILE_DOOR, _("sh_files_filecheck"));
2847 case 'P': SL_RETURN(SH_FILE_PORT, _("sh_files_filecheck"));
2848 case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck"));
2849 default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2850 }
2851
2852 /* notreached */
2853}
2854
2855/* concatenate statpath = testdir"/"d_name
2856 */
2857static int sh_files_fullpath (const char * testdir, const char * d_name,
2858 char * statpath)
2859{
2860 int llen = 0;
2861
2862 SL_ENTER(_("sh_files_fullpath"));
2863
2864 if (testdir != NULL)
2865 {
2866 if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) )
2867 SL_RETURN((-1),_("sh_files_fullpath"));
2868 sl_strlcpy(statpath, testdir, PATH_MAX - 1);
2869 }
2870 if (d_name != NULL)
2871 {
2872 if (llen > 1 || statpath[0] != '/')
2873 sl_strlcat(statpath, "/", PATH_MAX);
2874 if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX)
2875 SL_RETURN((-1),_("sh_files_fullpath"));
2876 sl_strlcat(statpath, d_name, PATH_MAX);
2877 }
2878 if (statpath == NULL)
2879 SL_RETURN((-1),_("sh_files_fullpath"));
2880 SL_RETURN((0),_("sh_files_fullpath"));
2881}
2882
2883/* -----------------------------------
2884 * Routines required for inotify
2885 * -----------------------------------
2886 */
2887int sh_files_search_dir(char * name, int * class,
2888 unsigned long *check_flags, int *reported,
2889 int * rdepth)
2890{
2891 volatile int retval = 0;
2892#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2893 sh_globstack_t * testPattern;
2894 zAVLCursor cursor;
2895#endif
2896 dirstack_t * item;
2897
2898 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2899 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2900
2901 item = zAVLSearch(zdirListOne, name);
2902
2903 if (item)
2904 {
2905 *check_flags = item->check_flags;
2906 *class = item->class;
2907 *reported = item->is_reported;
2908 *rdepth = item->rdepth;
2909 item->checked = S_FALSE;
2910 item->childs_checked = S_FALSE;
2911 item->is_reported = S_FALSE;
2912 retval = 1;
2913 goto out;
2914 }
2915
2916 item = zAVLSearch(zdirListTwo, name);
2917
2918 if (item)
2919 {
2920 *check_flags = item->check_flags;
2921 *class = item->class;
2922 *reported = item->is_reported;
2923 *rdepth = item->rdepth;
2924 item->checked = S_FALSE;
2925 item->childs_checked = S_FALSE;
2926 item->is_reported = S_FALSE;
2927 retval = 1;
2928 goto out;
2929 }
2930
2931#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2932 SH_MUTEX_LOCK(mutex_zglob);
2933 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
2934 testPattern;
2935 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
2936 {
2937 if (testPattern->type == SH_LIST_DIR1 ||
2938 testPattern->type == SH_LIST_DIR2)
2939 {
2940 if (0 == fnmatch(testPattern->name, name, FNM_PATHNAME|FNM_PERIOD))
2941 {
2942 *check_flags = testPattern->check_flags;
2943 *class = testPattern->class;
2944 *rdepth = testPattern->rdepth;
2945 retval = 1;
2946 break;
2947 }
2948
2949 }
2950 }
2951 SH_MUTEX_UNLOCK(mutex_zglob);
2952#endif
2953 out:
2954 ; /* 'label at end of compound statement' */
2955 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2956 return retval;
2957}
2958
2959int sh_files_search_file(char * name, int * class,
2960 unsigned long *check_flags, int *reported)
2961{
2962 volatile int retval = 0;
2963#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2964 sh_globstack_t * testPattern;
2965 zAVLCursor cursor;
2966#endif
2967 dirstack_t * item;
2968
2969 SH_MUTEX_LOCK(mutex_zfiles);
2970 item = zAVLSearch(zfileList, name);
2971
2972 if (item)
2973 {
2974 *check_flags = item->check_flags;
2975 *class = item->class;
2976 *reported = item->is_reported;
2977 retval = 1;
2978 }
2979 SH_MUTEX_UNLOCK(mutex_zfiles);
2980
2981#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2982 if (retval == 0)
2983 {
2984 SH_MUTEX_LOCK(mutex_zglob);
2985 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
2986 testPattern;
2987 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
2988 {
2989 if (testPattern->type == SH_LIST_FILE)
2990 {
2991 if (0 == fnmatch(testPattern->name, name,
2992 FNM_PATHNAME|FNM_PERIOD))
2993 {
2994 *check_flags = testPattern->check_flags;
2995 *class = testPattern->class;
2996 retval = 1;
2997 break;
2998 }
2999
3000 }
3001 }
3002 SH_MUTEX_UNLOCK(mutex_zglob);
3003 }
3004#endif
3005
3006 return retval;
3007}
3008
3009void sh_files_set_file_reported(const char * name)
3010{
3011 dirstack_t * item;
3012
3013 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
3014 item = zAVLSearch(zfileList, name);
3015
3016 if (item)
3017 {
3018 if (sh.flag.reportonce == S_TRUE)
3019 SET_SH_FFLAG_REPORTED(item->is_reported);
3020 }
3021 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
3022 return;
3023}
3024
3025void sh_files_clear_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 CLEAR_SH_FFLAG_REPORTED(item->is_reported);
3035 }
3036 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
3037 return;
3038}
3039
3040/* -----------------------------------
3041 *
3042 * The following two routines serve to
3043 * verify that the user has selected
3044 * a proper setup for file policies.
3045 *
3046 * -----------------------------------
3047 */
3048static int check_file(char * name)
3049{
3050 dirstack_t * pfilL;
3051 zAVLCursor cursor;
3052 volatile int retval = -1;
3053
3054 SL_ENTER(_("check_file"));
3055
3056 if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name))
3057 SL_RETURN(0, _("check_file"));
3058
3059 for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL;
3060 pfilL = (dirstack_t *) zAVLNext (&cursor))
3061 {
3062 if (0 == strcmp(name, pfilL->name) &&
3063 (pfilL->check_flags & MODI_ATM) == 0 &&
3064 (pfilL->check_flags & MODI_CTM) == 0 &&
3065 (pfilL->check_flags & MODI_MTM) == 0)
3066 {
3067 retval = 0;
3068 break;
3069 }
3070 }
3071
3072 SL_RETURN(retval, _("check_file"));
3073}
3074
3075static void * sh_dummy_pdirL;
3076
3077int sh_files_test_setup_int (zAVLTree * tree)
3078{
3079 int dlen, flen;
3080 zAVLCursor cursor1;
3081 zAVLCursor cursor2;
3082
3083 dirstack_t * pdirL;
3084 dirstack_t * pfilL;
3085
3086 SL_ENTER(_("sh_files_test_setup"));
3087
3088 sh_dummy_pdirL = (void *) &pdirL;
3089
3090 for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL;
3091 pdirL = (dirstack_t *) zAVLNext (&cursor1))
3092 {
3093 dlen = strlen(pdirL->name);
3094
3095 SH_MUTEX_LOCK(mutex_zfiles);
3096 for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL;
3097 pfilL = (dirstack_t *) zAVLNext (&cursor2))
3098 {
3099 flen = strlen(pfilL->name);
3100
3101 /* check whether file is in tree of dir
3102 */
3103 if ((pfilL->class == SH_LEVEL_READONLY) ||
3104 (pfilL->class == SH_LEVEL_NOIGNORE))
3105 {
3106 ; /* do nothing */
3107 }
3108 else
3109 {
3110 if ((flen > (dlen+1)) &&
3111 (pfilL->name[dlen] == '/') &&
3112 (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/
3113 (0 == strncmp(pfilL->name, pdirL->name, dlen)))
3114 {
3115 if ((pdirL->check_flags & MODI_ATM) != 0 ||
3116 (pdirL->check_flags & MODI_MTM) != 0 ||
3117 (pdirL->check_flags & MODI_CTM) != 0)
3118 {
3119 if (check_file (pdirL->name) != 0)
3120 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL,
3121 pdirL->name, pfilL->name);
3122 }
3123 }
3124 }
3125 }
3126 SH_MUTEX_UNLOCK(mutex_zfiles);
3127 }
3128
3129 SL_RETURN((0), _("sh_files_test_setup"));
3130}
3131
3132int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList)
3133{
3134 int retval = 0;
3135 zAVLCursor cursor;
3136 dirstack_t * first;
3137
3138 for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first;
3139 first = (dirstack_t *) zAVLNext (&cursor))
3140 {
3141
3142 if (NULL != zAVLSearch(secondList, first->name))
3143 {
3144 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
3145 first->name);
3146 retval = 1;
3147 }
3148 }
3149 return retval;
3150}
3151
3152extern void aud_exit (const char * file, int line, int fd);
3153
3154int sh_files_test_setup ()
3155{
3156 int retval;
3157
3158 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
3159 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
3160 /* Test for modifications allowed in ReadOnly directory
3161 */
3162 sh_files_test_setup_int (zdirListOne);
3163 sh_files_test_setup_int (zdirListTwo);
3164
3165 /* Test for files/dirz defined twice
3166 */
3167 retval = sh_files_test_double (zdirListOne, zdirListTwo);
3168 if (retval != 0)
3169 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
3170
3171 retval = sh_files_test_double (zdirListTwo, zdirListOne);
3172 if (retval != 0)
3173 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
3174 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
3175
3176 return 0;
3177}
3178
3179#endif
3180
3181#ifdef SH_CUTEST
3182#include "CuTest.h"
3183
3184void Test_file_lists (CuTest *tc)
3185{
3186#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
3187
3188 extern int hash_remove_tree_test(char * s, char * fullpath, size_t len_s);
3189
3190 char * test;
3191 int ret;
3192
3193 sh_files_pushfile_ro("/usr/test");
3194 sh_files_pushfile_ro("/usr/bin/test");
3195 sh_files_pushfile_ro("/usr/bin/foo/test");
3196
3197 sh_files_pushdir_ro("/usr");
3198 sh_files_pushdir_attr("/usr/bin");
3199 sh_files_pushdir_ro("/usr/bin/foo");
3200
3201 add_to_dirlist(zdirListOne);
3202 add_to_dirlist(zdirListTwo);
3203 add_to_filelist(zfileList);
3204
3205 test = sh_files_findfile("/usr/tes");
3206 CuAssertTrue(tc, test == NULL);
3207 test = sh_files_findfile("/usr/test");
3208 CuAssertPtrNotNull(tc, test);
3209 test = sh_files_findfile("/usr/testi");
3210 CuAssertTrue(tc, test == NULL);
3211 test = sh_files_findfile("/test");
3212 CuAssertTrue(tc, test == NULL);
3213
3214 test = sh_files_find_mostspecific_dir("/usr/bin/foo/test");
3215 CuAssertStrEquals(tc, "/usr/bin/foo", test);
3216 test = sh_files_find_mostspecific_dir("/usr/bin/test");
3217 CuAssertStrEquals(tc, "/usr/bin", test);
3218 test = sh_files_find_mostspecific_dir("/usr/test");
3219 CuAssertStrEquals(tc, "/usr", test);
3220 test = sh_files_find_mostspecific_dir("/test");
3221 CuAssertTrue(tc, test == NULL);
3222 test = sh_files_find_mostspecific_dir("/usr/foo/test");
3223 CuAssertStrEquals(tc, "/usr", test);
3224
3225 test = sh_files_find_mostspecific_dir("/usr/bin");
3226 CuAssertStrEquals(tc, "/usr/bin", test);
3227
3228 ret = hash_remove_tree_test("/usr", "/usr/test", strlen("/usr"));
3229 CuAssertIntEquals(tc, S_FALSE, ret);
3230 ret = hash_remove_tree_test("/usr", "/usr/testi", strlen("/usr"));
3231 CuAssertIntEquals(tc, S_TRUE, ret);
3232 ret = hash_remove_tree_test("/usr", "/usr/tes", strlen("/usr"));
3233 CuAssertIntEquals(tc, S_TRUE, ret);
3234
3235 ret = hash_remove_tree_test("/usr/bin", "/usr/test", strlen("/usr/bin"));
3236 CuAssertIntEquals(tc, S_FALSE, ret);
3237 ret = hash_remove_tree_test("/usr/bin", "/usr/testi", strlen("/usr/bin"));
3238 CuAssertIntEquals(tc, S_FALSE, ret);
3239 ret = hash_remove_tree_test("/usr/bin", "/usr/tes", strlen("/usr/bin"));
3240 CuAssertIntEquals(tc, S_FALSE, ret);
3241
3242 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/test", strlen("/usr/bin"));
3243 CuAssertIntEquals(tc, S_FALSE, ret);
3244 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/testi", strlen("/usr/bin"));
3245 CuAssertIntEquals(tc, S_TRUE, ret);
3246 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/tes", strlen("/usr/bin"));
3247 CuAssertIntEquals(tc, S_TRUE, ret);
3248
3249 ret = hash_remove_tree_test("/usr/bin", "/usr/bin", strlen("/usr/bin"));
3250 CuAssertIntEquals(tc, S_TRUE, ret);
3251 ret = hash_remove_tree_test("/usr", "/usr", strlen("/usr"));
3252 CuAssertIntEquals(tc, S_TRUE, ret);
3253 ret = hash_remove_tree_test("/usr", "/usrbin", strlen("/usr"));
3254 CuAssertIntEquals(tc, S_FALSE, ret);
3255 ret = hash_remove_tree_test("/", "/usrbin", strlen("/"));
3256 CuAssertIntEquals(tc, S_TRUE, ret);
3257 ret = hash_remove_tree_test("/", "/usr", strlen("/"));
3258 CuAssertIntEquals(tc, S_FALSE, ret);
3259
3260#else
3261 (void) tc; /* fix compiler warning */
3262 return;
3263#endif
3264}
3265
3266void Test_file_dequote (CuTest *tc)
3267{
3268#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
3269
3270 char str1[] = "1234567890";
3271 char str1a[] = "123456\\\"789\\r";
3272 char str1b[] = "12345678\\r9";
3273 char str1c[] = "12345678\\x0a_9";
3274 char str1d[] = "12345678\\007_9";
3275 char str1e[] = "123456789\\\\";
3276
3277 char str2[] = "1234567890\\xw";
3278 char str3[] = "1234567890\\xw99";
3279 char str4[] = "1234567890\\0ww";
3280 char str5[] = "12345\\g67890";
3281 char str6[] = "1234567890\\009a";
3282
3283 char *s, *p, *q;
3284 size_t lo, lr;
3285
3286 s = SH_ALLOC(64); sl_strlcpy(s, str1, 64); p = s; lo = strlen(s); lr = lo;
3287 q = sh_files_C_dequote(s, &lr);
3288 CuAssertPtrNotNull(tc, q);
3289 CuAssertTrue(tc, p == q);
3290 CuAssertTrue(tc, lr == lo);
3291
3292 s = SH_ALLOC(64); sl_strlcpy(s, str1a, 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, "123456\"789\r"));
3297 CuAssertTrue(tc, lr == (lo-2));
3298
3299 s = SH_ALLOC(64); sl_strlcpy(s, str1b, 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\r9"));
3304 CuAssertTrue(tc, lr == (lo-1));
3305
3306 s = SH_ALLOC(64); sl_strlcpy(s, str1c, 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, "12345678\x0a_9"));
3311 CuAssertTrue(tc, lr == (lo-3));
3312
3313 s = SH_ALLOC(64); sl_strlcpy(s, str1d, 64); p = s; lo = strlen(s); lr = lo;
3314 q = sh_files_C_dequote(s, &lr);
3315 CuAssertPtrNotNull(tc, q);
3316 CuAssertTrue(tc, p != q);
3317 CuAssertTrue(tc, 0 == strcmp(q, "12345678\007_9"));
3318 CuAssertTrue(tc, lr == (lo-3));
3319
3320 s = SH_ALLOC(64); sl_strlcpy(s, str1e, 64); p = s; lo = strlen(s); lr = lo;
3321 q = sh_files_C_dequote(s, &lr);
3322 CuAssertPtrNotNull(tc, q);
3323 CuAssertTrue(tc, p != q);
3324 CuAssertTrue(tc, 0 == strcmp(q, "123456789\\"));
3325 CuAssertTrue(tc, lr == (lo-1));
3326
3327 s = SH_ALLOC(64); sl_strlcpy(s, str2, 64); p = s; lo = strlen(s); lr = lo;
3328 q = sh_files_C_dequote(s, &lr);
3329 CuAssertTrue(tc, q == NULL);
3330 CuAssertTrue(tc, lr == 0);
3331
3332 s = SH_ALLOC(64); sl_strlcpy(s, str3, 64); p = s; lo = strlen(s); lr = lo;
3333 q = sh_files_C_dequote(s, &lr);
3334 CuAssertTrue(tc, q == NULL);
3335 CuAssertTrue(tc, lr == 0);
3336
3337 s = SH_ALLOC(64); sl_strlcpy(s, str4, 64); p = s; lo = strlen(s); lr = lo;
3338 q = sh_files_C_dequote(s, &lr);
3339 CuAssertTrue(tc, q == NULL);
3340 CuAssertTrue(tc, lr == 0);
3341
3342 s = SH_ALLOC(64); sl_strlcpy(s, str5, 64); p = s; lo = strlen(s); lr = lo;
3343 q = sh_files_C_dequote(s, &lr);
3344 CuAssertTrue(tc, q == NULL);
3345 CuAssertTrue(tc, lr == 0);
3346
3347 s = SH_ALLOC(64); sl_strlcpy(s, str6, 64); p = s; lo = strlen(s); lr = lo;
3348 q = sh_files_C_dequote(s, &lr);
3349 CuAssertTrue(tc, q == NULL);
3350 CuAssertTrue(tc, lr == 0);
3351
3352 return;
3353#else
3354 (void) tc; /* fix compiler warning */
3355 return;
3356#endif
3357}
3358#endif
3359
Note: See TracBrowser for help on using the repository browser.