source: trunk/src/sh_files.c@ 2

Last change on this file since 2 was 1, checked in by katerina, 19 years ago

Initial import

File size: 50.7 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#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <limits.h>
26
27#include <errno.h>
28
29/* Must be before <utime.h> on FreeBSD
30 */
31#include <sys/types.h>
32#include <unistd.h>
33
34#include <utime.h>
35
36
37#ifdef HAVE_DIRENT_H
38#include <dirent.h>
39#define NAMLEN(dirent) sl_strlen((dirent)->d_name)
40#else
41#define dirent direct
42#define NAMLEN(dirent) (dirent)->d_namlen
43#ifdef HAVE_SYS_NDIR_H
44#include <sys/ndir.h>
45#endif
46#ifdef HAVE_SYS_DIR_H
47#include <sys/dir.h>
48#endif
49#ifdef HAVE_NDIR_H
50#include <ndir.h>
51#endif
52#endif
53
54#ifdef HAVE_GLOB_H
55#include <glob.h>
56#endif
57
58#include "samhain.h"
59
60#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
61
62#include "sh_error.h"
63#include "sh_utils.h"
64#include "sh_unix.h"
65#include "sh_files.h"
66#include "sh_tiger.h"
67#include "sh_hash.h"
68#include "sh_ignore.h"
69#include "zAVLTree.h"
70
71#undef FIL__
72#define FIL__ _("sh_files.c")
73
74extern int safe_logger (int signal, int method, pid_t thepid);
75
76extern int flag_err_debug;
77extern int flag_err_info;
78
79int sh_files_reportonce(char * c)
80{
81 int i;
82 SL_ENTER(_("sh_files_reportonce"));
83 i = sh_util_flagval(c, &(sh.flag.reportonce));
84
85 SL_RETURN(i, _("sh_files_reportonce"));
86}
87
88int sh_files_fulldetail(char * c)
89{
90 int i;
91 SL_ENTER(_("sh_files_fulldetail"));
92 i = sh_util_flagval(c, &(sh.flag.fulldetail));
93
94 SL_RETURN((i), _("sh_files_fulldetail"));
95}
96
97
98typedef struct dir_struct {
99 long NumRegular;
100 long NumDirs;
101 long NumSymlinks;
102 long NumFifos;
103 long NumSockets;
104 long NumCDev;
105 long NumBDev;
106 long NumAll;
107 long TotalBytes;
108 char DirPath[PATH_MAX];
109} dir_type;
110
111typedef struct dirstack_entry {
112 char * name;
113 int class;
114 unsigned long check_mask;
115 int rdepth;
116 short checked;
117 short childs_checked;
118 short reported;
119 /* struct dirstack_entry * next; */
120} dirstack_t;
121
122
123/* the destructor
124 */
125void free_dirstack (void * inptr)
126{
127 dirstack_t * here;
128
129 SL_ENTER(_("free_dirstack"));
130 if (inptr == NULL)
131 SL_RET0(_("free_dirstack"));
132 else
133 here = (dirstack_t *) inptr;
134
135 if (here->name != NULL)
136 SH_FREE(here->name);
137 SH_FREE(here);
138 SL_RET0(_("free_dirstack"));
139}
140
141/* Function to return the key for indexing
142 * the argument
143 */
144zAVLKey zdirstack_key (void const * arg)
145{
146 const dirstack_t * sa = (const dirstack_t *) arg;
147 return (zAVLKey) sa->name;
148}
149
150
151static zAVLTree * zdirListOne = NULL;
152static zAVLTree * zdirListTwo = NULL;
153static zAVLTree * zfileList = NULL;
154
155
156static int sh_files_fullpath (char * testdir, char * d_name,
157 char * statpath);
158static int sh_files_pushdir (int class, char * str_s);
159static int sh_files_pushfile (int class, char * str_s);
160static int sh_files_checkdir (int class, int rdepth, char * dirName,
161 char * relativeName);
162static ShFileType sh_files_filecheck (int class, char * dirName,
163 char * fileName, int * reported,
164 int rsrcflag);
165
166static long MaxRecursionLevel = 0;
167
168/* set default recursion level
169 */
170int sh_files_setrecursion (char * flag_s)
171{
172 long flag = 0;
173 static int reject = 0;
174
175 SL_ENTER( _("sh_files_setrecursion"));
176
177 if (reject == 1)
178 SL_RETURN((-1), _("sh_files_setrecursion"));
179
180 if (sh.flag.opts == 1)
181 reject = 1;
182
183 if (flag_s != NULL)
184 flag = (int)(atof(flag_s));
185
186 if (flag >= 0 && flag <= 99)
187 MaxRecursionLevel = flag;
188 else
189 SL_RETURN((-1), _("sh_files_setrecursion"));
190
191 SL_RETURN((0), _("sh_files_setrecursion"));
192}
193
194
195unsigned long sh_files_chk ()
196{
197 zAVLCursor cursor;
198 ShFileType status;
199 unsigned long fcount = 0;
200
201 char * tmp = NULL;
202
203 dirstack_t * ptr;
204 char * base;
205 char * file;
206
207 SL_ENTER(_("sh_files_chk"));
208
209 for (ptr = (dirstack_t *) zAVLFirst(&cursor, zfileList); ptr;
210 ptr = (dirstack_t *) zAVLNext(&cursor))
211 {
212
213 if (sig_urgent > 0) {
214 SL_RETURN(fcount, _("sh_files_chk"));
215 }
216
217 if (ptr->checked == S_FALSE)
218 {
219 base = sh_util_basename (ptr->name);
220 file = sh_util_filename (ptr->name);
221#if defined(WITH_TPT)
222 tmp = sh_util_safe_name (ptr->name);
223#endif
224
225
226 if (flag_err_info == SL_TRUE)
227 {
228#if !defined(WITH_TPT)
229 tmp = sh_util_safe_name (ptr->name);
230#endif
231 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK,
232 tmp);
233 }
234
235 BREAKEXIT(sh_files_filecheck);
236 status = sh_files_filecheck (ptr->class, base, file,
237 (int *) &(ptr->reported), 0);
238
239 TPT(( 0, FIL__, __LINE__,
240 _("msg=<filecheck complete: %s> status=<%d> reported=<%d>\n"),
241 tmp, status, ptr->reported));
242
243 if (status == SH_FILE_UNKNOWN && ptr->reported == S_FALSE)
244 {
245 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
246 tmp, status));
247
248 if ( sh.flag.checkSum == SH_CHECK_INIT ||
249 sh_hash_have_it (ptr->name) >= 0)
250 {
251 if (S_FALSE == sh_ignore_chk_del(ptr->name))
252 {
253 if (0 != hashreport_missing(ptr->name,
254 (ptr->class == SH_LEVEL_ALLIGNORE) ?
255 ShDFLevel[ptr->class] :
256 ShDFLevel[SH_ERR_T_FILE])) {
257 if (tmp == NULL)
258 tmp = sh_util_safe_name (ptr->name);
259 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
260 ShDFLevel[ptr->class] :
261 ShDFLevel[SH_ERR_T_FILE],
262 FIL__, __LINE__, 0, MSG_FI_MISS,
263 tmp);
264 }
265 }
266 }
267 else /* not there at init, and still missing */
268 {
269 if (tmp == NULL)
270 tmp = sh_util_safe_name (ptr->name);
271 sh_error_handle (SH_ERR_NOTICE,
272 FIL__, __LINE__, 0,
273 MSG_FI_FAIL,
274 tmp);
275 }
276#ifndef REPLACE_OLD
277 /* this will tell that we have seen the file, and thus prevent
278 * deletion from the database, resulting in an incomplete
279 * message when the file reappears
280 */
281 if (sh.flag.checkSum != SH_CHECK_INIT)
282 sh_hash_set_visited_true(ptr->name);
283#else
284 if (sh.flag.checkSum != SH_CHECK_INIT)
285 sh_hash_set_missing(ptr->name);
286#endif
287 if (sh.flag.reportonce == S_TRUE)
288 ptr->reported = S_TRUE;
289 }
290 else
291 {
292 /* exists (status >= 0), but was missing (reported == TRUE)
293 */
294 if (status != SH_FILE_UNKNOWN && ptr->reported == S_TRUE)
295 {
296 ptr->reported = S_FALSE;
297 }
298 /* Catchall
299 */
300 else if (status == SH_FILE_UNKNOWN)
301 {
302 /* Thu Mar 7 15:09:40 CET 2002 Make sure missing file
303 * is reported if ptr->reported == S_TRUE because the
304 * file has been added.
305 */
306 if (sh_hash_have_it (ptr->name) >= 0)
307 {
308 if (S_FALSE == sh_ignore_chk_del(ptr->name))
309 {
310 if (0 != hashreport_missing(ptr->name,
311 (ptr->class == SH_LEVEL_ALLIGNORE) ?
312 ShDFLevel[ptr->class] :
313 ShDFLevel[SH_ERR_T_FILE])) {
314 if (tmp == NULL)
315 tmp = sh_util_safe_name (ptr->name);
316 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE)?
317 ShDFLevel[ptr->class] :
318 ShDFLevel[SH_ERR_T_FILE],
319 FIL__, __LINE__, 0, MSG_FI_MISS,
320 tmp);
321 }
322 }
323#ifndef REPLACE_OLD
324 if (sh.flag.checkSum != SH_CHECK_INIT)
325 sh_hash_set_visited_true(ptr->name);
326#else
327 /* delete from database
328 */
329 if (sh.flag.checkSum != SH_CHECK_INIT)
330 sh_hash_set_missing(ptr->name);
331#endif
332 }
333 else
334 {
335 if (tmp == NULL)
336 tmp = sh_util_safe_name (ptr->name);
337 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
338 MSG_FI_FAIL,
339 tmp);
340 if (sh.flag.checkSum != SH_CHECK_INIT)
341 sh_hash_set_visited_true(ptr->name);
342 }
343 }
344 ++fcount;
345 }
346
347 if (tmp != NULL)
348 {
349 SH_FREE(tmp);
350 tmp = NULL;
351 }
352 SH_FREE(file);
353 SH_FREE(base);
354
355 ptr->checked = S_TRUE;
356 }
357 }
358
359 SL_RETURN(fcount, _("sh_files_chk"));
360}
361
362int sh_files_delfilestack ()
363{
364 SL_ENTER(_("sh_files_delfilestack"));
365
366 zAVLFreeTree (zfileList, free_dirstack);
367 zfileList = NULL;
368
369 SL_RETURN(0, _("sh_files_delfilestack"));
370}
371
372int sh_files_setrec_int (zAVLTree * tree)
373{
374 dirstack_t * ptr;
375 zAVLCursor avlcursor;
376
377 SL_ENTER(_("sh_files_setrec"));
378 if (tree != NULL) {
379 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
380 ptr = (dirstack_t *) zAVLNext(&avlcursor))
381 {
382 if (ptr->rdepth < (-1) || ptr->rdepth > 99)
383 {
384 ptr->rdepth = MaxRecursionLevel;
385 }
386 if (ptr->rdepth == (-1) && sh.flag.checkSum != SH_CHECK_INIT)
387 hash_remove_tree (ptr->name);
388 }
389 }
390 SL_RETURN(0, _("sh_files_setrec"));
391}
392
393int sh_files_setrec ()
394{
395 sh_files_setrec_int(zdirListOne);
396 return sh_files_setrec_int(zdirListTwo);
397}
398
399zAVLTree * sh_files_deldirstack_int (zAVLTree * ptr)
400{
401 SL_ENTER(_("sh_files_deldirstack"));
402
403 zAVLFreeTree (ptr, free_dirstack);
404
405 SL_RETURN(NULL, _("sh_files_deldirstack"));
406}
407
408int sh_files_deldirstack ()
409{
410 zdirListOne = sh_files_deldirstack_int(zdirListOne);
411 zdirListTwo = sh_files_deldirstack_int(zdirListTwo);
412 return 0;
413}
414
415void sh_files_reset()
416{
417 dirstack_t * ptr;
418 zAVLCursor avlcursor;
419
420 SL_ENTER(_("sh_files_reset"));
421
422 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, zfileList); ptr;
423 ptr = (dirstack_t *) zAVLNext(&avlcursor))
424 ptr->checked = 0;
425
426 SL_RET0(_("sh_files_reset"));
427}
428
429void sh_dirs_reset()
430{
431 dirstack_t * ptr;
432 zAVLCursor avlcursor1;
433 zAVLCursor avlcursor2;
434
435 SL_ENTER(_("sh_dirs_reset"));
436
437 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor1, zdirListOne); ptr;
438 ptr = (dirstack_t *) zAVLNext(&avlcursor1))
439 ptr->checked = 0;
440
441 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor2, zdirListTwo); ptr;
442 ptr = (dirstack_t *) zAVLNext(&avlcursor2))
443 ptr->checked = 0;
444
445 SL_RET0(_("sh_dirs_reset"));
446}
447
448
449int sh_files_pushfile_prelink (char * str_s)
450{
451 return (sh_files_pushfile (SH_LEVEL_PRELINK, str_s));
452}
453
454int sh_files_pushfile_user0 (char * str_s)
455{
456 return (sh_files_pushfile (SH_LEVEL_USER0, str_s));
457}
458
459
460int sh_files_pushfile_user1 (char * str_s)
461{
462 return (sh_files_pushfile (SH_LEVEL_USER1, str_s));
463}
464
465
466int sh_files_pushfile_ro (char * str_s)
467{
468 return (sh_files_pushfile (SH_LEVEL_READONLY, str_s));
469}
470
471int sh_files_pushfile_attr (char * str_s)
472{
473 return (sh_files_pushfile (SH_LEVEL_ATTRIBUTES, str_s));
474}
475
476int sh_files_pushfile_log (char * str_s)
477{
478 return (sh_files_pushfile (SH_LEVEL_LOGFILES, str_s));
479}
480
481int sh_files_pushfile_glog (char * str_s)
482{
483 return (sh_files_pushfile (SH_LEVEL_LOGGROW, str_s));
484}
485
486int sh_files_pushfile_noig (char * str_s)
487{
488 return (sh_files_pushfile (SH_LEVEL_NOIGNORE, str_s));
489}
490
491int sh_files_pushfile_allig (char * str_s)
492{
493 return (sh_files_pushfile (SH_LEVEL_ALLIGNORE, str_s));
494}
495
496
497static void sh_files_set_mask (unsigned long * mask,
498 unsigned long val, int act)
499{
500 SL_ENTER(_("sh_files_set_mask"));
501
502 if (act == 0)
503 (*mask) = val;
504 else if (act > 0)
505 (*mask) |= val;
506 else
507 (*mask) &= ~val;
508
509 SL_RET0(_("sh_files_set_mask"));
510}
511
512/* set mask(class)
513 */
514static int sh_files_parse_mask (unsigned long * mask, char * str)
515{
516 int l, i = 0, act = 0, k = 0;
517 char myword[64];
518
519 SL_ENTER(_("sh_files_parse_mask"));
520
521 if (str == NULL)
522 {
523 SL_RETURN ( (-1), _("sh_files_parse_mask"));
524 }
525 else
526 l = sl_strlen(str);
527
528 while (i < l) {
529 if (str[i] == '\0')
530 break;
531 if (str[i] == ' ' || str[i] == '\t' || str[i] == ',')
532 {
533 ++i;
534 continue;
535 }
536
537 if (str[i] == '+')
538 {
539 act = +1; ++i;
540 continue;
541 }
542 else if (str[i] == '-')
543 {
544 act = -1; ++i;
545 continue;
546 }
547 else /* a word */
548 {
549 k = 0;
550 while (k < 63 && str[i] != ' ' && str[i] != '\t' && str[i] != ','
551 && str[i] != '+' && str[i] != '-' && str[i] != '\0') {
552 myword[k] = str[i];
553 ++i; ++k;
554 }
555 myword[k] = '\0';
556
557/* checksum */
558 if (0 == strncmp(myword, _("CHK"), 3))
559 sh_files_set_mask (mask, MODI_CHK, act);
560/* link */
561 if (0 == strncmp(myword, _("LNK"), 3))
562 sh_files_set_mask (mask, MODI_LNK, act);
563/* inode */
564 if (0 == strncmp(myword, _("RDEV"), 3))
565 sh_files_set_mask (mask, MODI_RDEV, act);
566/* inode */
567 if (0 == strncmp(myword, _("INO"), 3))
568 sh_files_set_mask (mask, MODI_INO, act);
569/* user */
570 if (0 == strncmp(myword, _("USR"), 3))
571 sh_files_set_mask (mask, MODI_USR, act);
572/* group */
573 if (0 == strncmp(myword, _("GRP"), 3))
574 sh_files_set_mask (mask, MODI_GRP, act);
575/* mtime */
576 if (0 == strncmp(myword, _("MTM"), 3))
577 sh_files_set_mask (mask, MODI_MTM, act);
578/* ctime */
579 if (0 == strncmp(myword, _("CTM"), 3))
580 sh_files_set_mask (mask, MODI_CTM, act);
581/* atime */
582 if (0 == strncmp(myword, _("ATM"), 3))
583 sh_files_set_mask (mask, MODI_ATM, act);
584/* size */
585 if (0 == strncmp(myword, _("SIZ"), 3))
586 sh_files_set_mask (mask, MODI_SIZ, act);
587/* file mode */
588 if (0 == strncmp(myword, _("MOD"), 3))
589 sh_files_set_mask (mask, MODI_MOD, act);
590/* hardlinks */
591 if (0 == strncmp(myword, _("HLN"), 3))
592 sh_files_set_mask (mask, MODI_HLN, act);
593
594 }
595 }
596 SL_RETURN ( (0), _("sh_files_parse_mask"));
597}
598
599int sh_files_redef_prelink(char * str)
600{
601 return (sh_files_parse_mask(&mask_PRELINK, str));
602}
603int sh_files_redef_user0(char * str)
604{
605 return (sh_files_parse_mask(&mask_USER0, str));
606}
607int sh_files_redef_user1(char * str)
608{
609 return (sh_files_parse_mask(&mask_USER1, str));
610}
611int sh_files_redef_readonly(char * str)
612{
613 return (sh_files_parse_mask(&mask_READONLY, str));
614}
615int sh_files_redef_loggrow(char * str)
616{
617 return (sh_files_parse_mask(&mask_LOGGROW, str));
618}
619int sh_files_redef_logfiles(char * str)
620{
621 return (sh_files_parse_mask(&mask_LOGFILES, str));
622}
623int sh_files_redef_attributes(char * str)
624{
625 return (sh_files_parse_mask(&mask_ATTRIBUTES, str));
626}
627int sh_files_redef_noignore(char * str)
628{
629 return (sh_files_parse_mask(&mask_NOIGNORE, str));
630}
631int sh_files_redef_allignore(char * str)
632{
633 return (sh_files_parse_mask(&mask_ALLIGNORE, str));
634}
635
636unsigned long sh_files_maskof (int class)
637{
638 switch (class)
639 {
640 case SH_LEVEL_READONLY:
641 return (unsigned long) mask_READONLY;
642 case SH_LEVEL_ATTRIBUTES:
643 return (unsigned long) mask_ATTRIBUTES;
644 case SH_LEVEL_LOGFILES:
645 return (unsigned long) mask_LOGFILES;
646 case SH_LEVEL_LOGGROW:
647 return (unsigned long) mask_LOGGROW;
648 case SH_LEVEL_ALLIGNORE:
649 return (unsigned long) mask_ALLIGNORE;
650 case SH_LEVEL_NOIGNORE:
651 return (unsigned long) mask_NOIGNORE;
652 case SH_LEVEL_USER0:
653 return (unsigned long) mask_USER0;
654 case SH_LEVEL_USER1:
655 return (unsigned long) mask_USER1;
656 case SH_LEVEL_PRELINK:
657 return (unsigned long) mask_PRELINK;
658 default:
659 return (unsigned long) 0;
660 }
661}
662
663#ifdef HAVE_GLOB_H
664int sh_files_has_metachar (const char * str)
665{
666 SL_ENTER(_("sh_files_has_metachar"));
667 if (NULL != strchr(str, '*'))
668 SL_RETURN(1, _("sh_files_has_metachar"));
669 else if (NULL != strchr(str, '?'))
670 SL_RETURN(1, _("sh_files_has_metachar"));
671 else if (NULL != (strchr(str, '[')))
672 SL_RETURN(1, _("sh_files_has_metachar"));
673 else
674 SL_RETURN(0, _("sh_files_has_metachar"));
675}
676
677
678int sh_files_globerr (const char * epath, int errnum)
679{
680 char * p;
681
682 SL_ENTER(_("sh_files_globerr"));
683
684 p = sh_util_safe_name (epath);
685 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_FI_GLOB,
686 sh_error_message (errnum), p);
687 SH_FREE(p);
688
689 SL_RETURN(0, _("sh_files_globerr"));
690}
691
692/* #ifdef HAVE_GLOB_H
693 */
694#endif
695
696int sh_files_push_file_int (int class, const char * str_s, int len)
697{
698 dirstack_t * new_item_ptr;
699 char * fileName;
700 int ret;
701
702 SL_ENTER(_("sh_files_push_file_int"));
703
704 fileName = SH_ALLOC(len+1);
705 sl_strlcpy(fileName, str_s, len+1);
706
707 new_item_ptr = (dirstack_t *) SH_ALLOC (sizeof(dirstack_t));
708
709 new_item_ptr->name = fileName;
710 new_item_ptr->class = class;
711 new_item_ptr->check_mask = sh_files_maskof(class);
712 new_item_ptr->rdepth = 0;
713 new_item_ptr->checked = S_FALSE;
714 new_item_ptr->reported = S_FALSE;
715 new_item_ptr->childs_checked = S_FALSE;
716
717 if (zfileList == NULL)
718 {
719 zfileList = zAVLAllocTree (zdirstack_key);
720 if (zfileList == NULL)
721 {
722 (void) safe_logger (0, 0, getpid());
723 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
724 }
725 }
726
727 ret = zAVLInsert (zfileList, new_item_ptr);
728
729 if (-1 == ret)
730 {
731 (void) safe_logger (0, 0, getpid());
732 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
733 }
734 if (3 == ret)
735 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
736 fileName);
737
738 SL_RETURN(0, _("sh_files_push_file_int"));
739}
740
741
742static int sh_files_pushfile (int class, char * str_s)
743{
744 char * tmp;
745 int len;
746#ifdef HAVE_GLOB_H
747 glob_t pglob;
748 int globstatus = -1;
749 unsigned int gloop;
750#endif
751
752 static int reject = 0;
753
754 SL_ENTER(_("sh_files_pushfile"));
755
756 if (reject == 1)
757 SL_RETURN((-1),_("sh_files_pushfile"));
758
759 /* if we push a filename from the command line, make sure it
760 * is the only one -- and will stay the only one
761 */
762 if (sh.flag.opts == 1)
763 {
764 sh_files_delfilestack ();
765 sh_files_deldirstack ();
766 reject = 1;
767 }
768
769 if (str_s == NULL)
770 SL_RETURN((-1),_("sh_files_pushfile"));
771
772 len = sl_strlen(str_s);
773
774 if (len >= PATH_MAX)
775 {
776 /* Name too long
777 */
778 tmp = sh_util_safe_name (str_s);
779 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
780 tmp);
781 SH_FREE(tmp);
782 SL_RETURN((-1),_("sh_files_pushfile"));
783 }
784 else if (len < 1)
785 {
786 /* Should not happen (str_s == NULL caught further above)
787 */
788 SL_RETURN((-1),_("sh_files_pushfile"));
789 }
790 else if (str_s[0] != '/')
791 {
792 /* Not an absolute path
793 */
794 tmp = sh_util_safe_name (str_s);
795 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
796 tmp);
797 SH_FREE(tmp);
798 SL_RETURN((-1),_("sh_files_pushfile"));
799 }
800 else
801 {
802 /* remove a terminating '/', take care of the
803 * special case of the root directory.
804 */
805 if (str_s[len-1] == '/' && len > 1)
806 {
807 str_s[len-1] = '\0';
808 --len;
809 }
810
811 }
812
813#ifdef HAVE_GLOB_H
814 if (0 == sh_files_has_metachar(str_s))
815 {
816 sh_files_push_file_int (class, str_s, len);
817 }
818 else
819 {
820 pglob.gl_offs = 0;
821 globstatus = glob (str_s, 0, sh_files_globerr, &pglob);
822
823 if (globstatus == 0 && pglob.gl_pathc > 0)
824 {
825 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
826 sh_files_push_file_int (class, pglob.gl_pathv[gloop],
827 sl_strlen(pglob.gl_pathv[gloop]));
828 }
829 else
830 {
831 tmp = sh_util_safe_name (str_s);
832
833 if (pglob.gl_pathc == 0
834#ifdef GLOB_NOMATCH
835 || globstatus == GLOB_NOMATCH
836#endif
837 )
838 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
839 globstatus, MSG_FI_GLOB,
840 _("No matches found"), tmp);
841#ifdef GLOB_NOSPACE
842 else if (globstatus == GLOB_NOSPACE)
843 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
844 globstatus, MSG_FI_GLOB,
845 _("Out of memory"), tmp);
846#endif
847#ifdef GLOB_ABORTED
848 else if (globstatus == GLOB_ABORTED)
849 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
850 globstatus, MSG_FI_GLOB,
851 _("Read error"), tmp);
852#endif
853 else
854 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
855 globstatus, MSG_FI_GLOB,
856 _("Unknown error"), tmp);
857
858 SH_FREE(tmp);
859
860 }
861
862 globfree(&pglob);
863 }
864
865#else
866 sh_files_push_file_int (class, str_s, len);
867#endif
868
869 SL_RETURN((0),_("sh_files_pushfile"));
870}
871
872
873/* ------ directories ----- */
874
875int sh_files_is_allignore_int (char * str, zAVLTree * tree)
876{
877 dirstack_t * ptr;
878
879 SL_ENTER(_("sh_files_is_allignore"));
880
881 if (tree)
882 {
883 ptr = zAVLSearch(tree, str);
884 if (ptr)
885 {
886 if (ptr->class == SH_LEVEL_ALLIGNORE)
887 SL_RETURN( 1, _("sh_files_is_allignore"));
888 else
889 SL_RETURN( 0, _("sh_files_is_allignore"));
890 }
891 }
892 SL_RETURN( 0, _("sh_files_is_allignore"));
893}
894
895int sh_files_is_allignore (char * str)
896{
897 if (1 == sh_files_is_allignore_int(str, zdirListOne))
898 return 1;
899 if (NULL == zdirListTwo)
900 return 0;
901 return sh_files_is_allignore_int(str, zdirListTwo);
902}
903
904unsigned long sh_dirs_chk (int which)
905{
906 zAVLTree * tree;
907 zAVLCursor cursor;
908 dirstack_t * ptr;
909 dirstack_t * dst_ptr;
910 int status;
911 unsigned long dcount = 0;
912 char * tmp;
913
914 SL_ENTER(_("sh_dirs_chk"));
915
916 if (which == 1)
917 tree = zdirListOne;
918 else
919 tree = zdirListTwo;
920
921 for (ptr = (dirstack_t *) zAVLFirst(&cursor, tree); ptr;
922 ptr = (dirstack_t *) zAVLNext(&cursor))
923 {
924 if (sig_urgent > 0) {
925 SL_RETURN(dcount, _("sh_dirs_chk"));
926 }
927
928 if (ptr->checked == S_FALSE)
929 {
930 /* 28 Aug 2001 check the top level directory
931 */
932 status = S_FALSE;
933 dst_ptr = zAVLSearch(zfileList, ptr->name);
934 if (dst_ptr)
935 {
936 if (dst_ptr->checked == S_FALSE)
937 {
938 BREAKEXIT(sh_files_filecheck);
939 sh_files_filecheck (dst_ptr->class, ptr->name,
940 NULL, &status, 0);
941 dst_ptr->checked = S_TRUE;
942 status = S_TRUE;
943 break;
944 }
945 else
946 {
947 status = S_TRUE;
948 break;
949 }
950 }
951
952 if (status == S_FALSE)
953 sh_files_filecheck (ptr->class, ptr->name, NULL, &status, 0);
954
955 BREAKEXIT(sh_files_checkdir);
956 status = sh_files_checkdir (ptr->class, ptr->rdepth, ptr->name,
957 ptr->name);
958
959 if (status < 0 && ptr->reported == S_FALSE)
960 {
961 /* directory is missing
962 */
963 if (S_FALSE == sh_ignore_chk_del(ptr->name))
964 {
965 if (0 != hashreport_missing(ptr->name,
966 (ptr->class == SH_LEVEL_ALLIGNORE) ?
967 ShDFLevel[ptr->class] :
968 ShDFLevel[SH_ERR_T_DIR])) {
969 tmp = sh_util_safe_name (ptr->name);
970 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
971 ShDFLevel[ptr->class] :
972 ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__,
973 0, MSG_FI_MISS, tmp);
974 SH_FREE(tmp);
975 }
976 }
977 if (sh.flag.reportonce == S_TRUE)
978 ptr->reported = S_TRUE;
979 }
980 else
981 {
982 /* exists (status >= 0), but was missing (reported == TRUE)
983 */
984 if (status >= 0 && ptr->reported == S_TRUE)
985 {
986 ptr->reported = S_FALSE;
987#if 0
988 /* obsoleted (really?) by the mandatory sh_files_filecheck()
989 * above, which will catch missing directories anyway
990 */
991 tmp = sh_util_safe_name (ptr->name);
992 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
993 ShDFLevel[ptr->class] :
994 ShDFLevel[SH_ERR_T_DIR],
995 FIL__, __LINE__, 0, MSG_FI_ADD,
996 tmp);
997 SH_FREE(tmp);
998#endif
999 }
1000 else if (status == SH_FILE_UNKNOWN)
1001 {
1002 /* catchall
1003 */
1004 tmp = sh_util_safe_name (ptr->name);
1005 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
1006 MSG_FI_FAIL,
1007 tmp);
1008 SH_FREE(tmp);
1009 if (sh.flag.checkSum != SH_CHECK_INIT)
1010 sh_hash_set_visited_true(ptr->name);
1011 }
1012
1013 ++dcount;
1014 }
1015 ptr->checked = S_TRUE;
1016 }
1017
1018 if (sig_urgent > 0) {
1019 SL_RETURN(dcount, _("sh_dirs_chk"));
1020 }
1021
1022 }
1023 SL_RETURN(dcount, _("sh_dirs_chk"));
1024}
1025
1026int sh_files_pushdir_prelink (char * str_s)
1027{
1028 return (sh_files_pushdir (SH_LEVEL_PRELINK, str_s));
1029}
1030
1031int sh_files_pushdir_user0 (char * str_s)
1032{
1033 return (sh_files_pushdir (SH_LEVEL_USER0, str_s));
1034}
1035
1036int sh_files_pushdir_user1 (char * str_s)
1037{
1038 return (sh_files_pushdir (SH_LEVEL_USER1, str_s));
1039}
1040
1041int sh_files_pushdir_attr (char * str_s)
1042{
1043 return (sh_files_pushdir (SH_LEVEL_ATTRIBUTES, str_s));
1044}
1045
1046int sh_files_pushdir_ro (char * str_s)
1047{
1048 return (sh_files_pushdir (SH_LEVEL_READONLY, str_s));
1049}
1050
1051int sh_files_pushdir_log (char * str_s)
1052{
1053 return (sh_files_pushdir (SH_LEVEL_LOGFILES, str_s));
1054}
1055
1056int sh_files_pushdir_glog (char * str_s)
1057{
1058 return (sh_files_pushdir (SH_LEVEL_LOGGROW, str_s));
1059}
1060
1061int sh_files_pushdir_noig (char * str_s)
1062{
1063 return (sh_files_pushdir (SH_LEVEL_NOIGNORE, str_s));
1064}
1065
1066int sh_files_pushdir_allig (char * str_s)
1067{
1068 return (sh_files_pushdir (SH_LEVEL_ALLIGNORE, str_s));
1069}
1070
1071static int which_dirList = 1;
1072
1073int set_dirList (int which)
1074{
1075 if (which == 2)
1076 which_dirList = 2;
1077 else
1078 which_dirList = 1;
1079 return 0;
1080}
1081
1082int sh_files_push_dir_int (int class, char * tail, int len, int rdepth)
1083{
1084 zAVLTree * tree;
1085 dirstack_t * new_item_ptr;
1086 char * dirName;
1087 int ret;
1088
1089 SL_ENTER(_("sh_files_push_dir_int"));
1090
1091 dirName = SH_ALLOC(len+1);
1092 sl_strlcpy(dirName, tail, len+1);
1093
1094 new_item_ptr = (dirstack_t * ) SH_ALLOC (sizeof(dirstack_t));
1095
1096 new_item_ptr->name = dirName;
1097 new_item_ptr->class = class;
1098 new_item_ptr->check_mask = sh_files_maskof(class);
1099 new_item_ptr->rdepth = rdepth;
1100 new_item_ptr->checked = S_FALSE;
1101 new_item_ptr->reported = S_FALSE;
1102 new_item_ptr->childs_checked = S_FALSE;
1103
1104 if (which_dirList == 1)
1105 {
1106 tree = zdirListOne;
1107 }
1108 else
1109 {
1110 tree = zdirListTwo;
1111 }
1112
1113 if (tree == NULL)
1114 {
1115 tree = zAVLAllocTree (zdirstack_key);
1116 if (tree == NULL)
1117 {
1118 (void) safe_logger (0, 0, getpid());
1119 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1120 }
1121 if (which_dirList == 1)
1122 zdirListOne = tree;
1123 else
1124 zdirListTwo = tree;
1125 }
1126
1127 ret = zAVLInsert (tree, new_item_ptr);
1128
1129 if (-1 == ret)
1130 {
1131 (void) safe_logger (0, 0, getpid());
1132 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1133 }
1134 if (3 == ret)
1135 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
1136 dirName);
1137
1138 SL_RETURN(0, _("sh_files_push_dir_int"));
1139}
1140
1141static int sh_files_pushdir (int class, char * str_s)
1142{
1143 char * tmp;
1144 int len;
1145 int rdepth = 0;
1146 char * tail = NULL;
1147
1148#ifdef HAVE_GLOB_H
1149 glob_t pglob;
1150 int globstatus = -1;
1151 unsigned int gloop;
1152#endif
1153
1154 SL_ENTER(_("sh_files_pushdir"));
1155
1156 if (sh.flag.opts == 1) {
1157 sh_files_delfilestack ();
1158 sh_files_deldirstack ();
1159 }
1160
1161 if (str_s == NULL)
1162 SL_RETURN((-1), _("sh_files_pushdir"));
1163
1164
1165 if (str_s[0] != '/')
1166 {
1167 rdepth = strtol(str_s, &tail, 10);
1168 if (tail == str_s)
1169 SL_RETURN((-1), _("sh_files_pushdir"));
1170 }
1171 else
1172 tail = str_s;
1173
1174
1175 if (rdepth < (-1) || tail == str_s || rdepth > 99)
1176 rdepth = (-2);
1177
1178 len = sl_strlen(tail);
1179
1180 if (len >= PATH_MAX)
1181 {
1182 tmp = sh_util_safe_name (tail);
1183 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1184 tmp);
1185 SH_FREE(tmp);
1186 SL_RETURN((-1), _("sh_files_pushdir"));
1187 }
1188 else if (len < 1)
1189 {
1190 SL_RETURN((-1), _("sh_files_pushdir"));
1191 }
1192 else if (tail[0] != '/')
1193 {
1194 tmp = sh_util_safe_name (tail);
1195 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1196 tmp);
1197 SH_FREE(tmp);
1198 SL_RETURN((-1), _("sh_files_pushdir"));
1199 }
1200 else
1201 {
1202
1203 if (tail[len-1] == '/' && len > 1)
1204 {
1205 tail[len-1] = '\0';
1206 --len;
1207 }
1208
1209 }
1210
1211#ifdef HAVE_GLOB_H
1212 if (0 == sh_files_has_metachar(tail))
1213 {
1214 sh_files_push_dir_int (class, tail, len, rdepth);
1215 }
1216 else
1217 {
1218 pglob.gl_offs = 0;
1219 globstatus = glob (tail, 0, sh_files_globerr, &pglob);
1220
1221 if (globstatus == 0 && pglob.gl_pathc > 0)
1222 {
1223 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
1224 sh_files_push_dir_int (class,
1225 pglob.gl_pathv[gloop],
1226 sl_strlen(pglob.gl_pathv[gloop]),
1227 rdepth);
1228 }
1229 else
1230 {
1231 tmp = sh_util_safe_name (tail);
1232
1233 if (pglob.gl_pathc == 0
1234#ifdef GLOB_NOMATCH
1235 || globstatus == GLOB_NOMATCH
1236#endif
1237 )
1238 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1239 globstatus, MSG_FI_GLOB,
1240 _("No matches found"), tmp);
1241#ifdef GLOB_NOSPACE
1242 else if (globstatus == GLOB_NOSPACE)
1243 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1244 globstatus, MSG_FI_GLOB,
1245 _("Out of memory"), tmp);
1246#endif
1247#ifdef GLOB_ABORTED
1248 else if (globstatus == GLOB_ABORTED)
1249 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1250 globstatus, MSG_FI_GLOB,
1251 _("Read error"), tmp);
1252#endif
1253 else
1254 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1255 globstatus, MSG_FI_GLOB,
1256 _("Unknown error"), tmp);
1257 SH_FREE(tmp);
1258 }
1259
1260 globfree(&pglob);
1261 }
1262#else
1263 sh_files_push_dir_int (class, tail, len, rdepth);
1264#endif
1265
1266 SL_RETURN((0), _("sh_files_pushdir"));
1267}
1268
1269struct sh_dirent {
1270 /* char sh_d_name[NAME_MAX + 2]; */
1271 char * sh_d_name;
1272 struct sh_dirent * next;
1273};
1274
1275static void kill_sh_dirlist (struct sh_dirent * dirlist)
1276{
1277 struct sh_dirent * this;
1278
1279 while (dirlist)
1280 {
1281 this = dirlist->next;
1282 SH_FREE(dirlist->sh_d_name);
1283 SH_FREE(dirlist);
1284 dirlist = this;
1285 }
1286 return;
1287}
1288
1289/* -- add an entry to a directory listing
1290 */
1291static struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry,
1292 struct sh_dirent * dirlist)
1293{
1294 struct sh_dirent * this;
1295 int i;
1296
1297 if (thisEntry == NULL)
1298 return dirlist;
1299
1300 i = sl_strlen(thisEntry->d_name);
1301 if (i == 0)
1302 return dirlist;
1303 ++i;
1304
1305 this = SH_ALLOC(sizeof(struct sh_dirent));
1306 if (!this)
1307 return dirlist;
1308
1309 this->sh_d_name = SH_ALLOC(i);
1310 sl_strlcpy(this->sh_d_name, thisEntry->d_name, i);
1311
1312 this->next = dirlist;
1313 return this;
1314}
1315
1316static int sh_check_hardlinks = S_TRUE;
1317
1318/* Simply sets our boolean as to whether this check is active
1319 */
1320int sh_files_check_hardlinks (char * opt)
1321{
1322 int i;
1323 SL_ENTER(_("sh_files_check_hardlinks"));
1324 i = sh_util_flagval(opt, &sh_check_hardlinks);
1325 SL_RETURN(i, _("sh_files_check_hardlinks"));
1326}
1327
1328struct sh_hle_struct {
1329 long offset;
1330 char * path;
1331 struct sh_hle_struct * next;
1332};
1333
1334static struct sh_hle_struct * sh_hl_exc = NULL;
1335
1336int sh_files_hle_reg (char * str)
1337{
1338 long offset;
1339 size_t len;
1340 char * path;
1341
1342 struct sh_hle_struct * tmp = sh_hl_exc;
1343
1344 SL_ENTER(_("sh_files_hle_reg"));
1345
1346 /* Free the linked list if called with NULL argument
1347 */
1348 if (str == NULL)
1349 {
1350 while (tmp)
1351 {
1352 sh_hl_exc = tmp->next;
1353 SH_FREE(tmp->path);
1354 SH_FREE(tmp);
1355 tmp = sh_hl_exc;
1356 }
1357 sh_hl_exc = NULL;
1358 SL_RETURN(0, _("sh_files_hle_reg"));
1359 }
1360
1361 /* We expect 'offset:/path'
1362 */
1363 offset = strtol(str, &path, 0);
1364 if ((path == NULL) || (*path == '\0') || (*path != ':') || (path[1] != '/'))
1365 {
1366 SL_RETURN(-1, _("sh_files_hle_reg"));
1367 }
1368 ++path;
1369 len = 1 + sl_strlen(path);
1370
1371 tmp = SH_ALLOC(sizeof(struct sh_hle_struct));
1372 tmp->path = SH_ALLOC(len);
1373 sl_strlcpy (tmp->path, path, len);
1374 tmp->offset = offset;
1375 tmp->next = sh_hl_exc;
1376 sh_hl_exc = tmp;
1377
1378 SL_RETURN(0, _("sh_files_hle_reg"));
1379}
1380
1381#if !defined(HOST_IS_DARWIN)
1382static int sh_files_hle_test (int offset, char * path)
1383{
1384 struct sh_hle_struct * tmp = sh_hl_exc;
1385
1386 SL_ENTER(_("sh_files_hle_reg"));
1387
1388 while(tmp)
1389 {
1390 if ((offset == tmp->offset) && (0 == strcmp(path, tmp->path)))
1391 {
1392 SL_RETURN(0, _("sh_files_hle_test"));
1393 }
1394 tmp = tmp->next;
1395 }
1396 SL_RETURN(-1, _("sh_files_hle_test"));
1397}
1398#endif
1399
1400/* -- check a single directory and its content
1401 */
1402static int sh_files_checkdir (int iclass, int idepth, char * iname,
1403 char * relativeName)
1404{
1405 struct sh_dirent * dirlist = NULL;
1406 struct sh_dirent * dirlist_orig = NULL;
1407
1408 DIR * thisDir = NULL;
1409 struct dirent * thisEntry;
1410 int status;
1411 int dummy = S_FALSE;
1412 dir_type theDir;
1413 ShFileType checkit;
1414
1415
1416 file_type theFile;
1417 char * tmpname;
1418 char * tmpcat;
1419
1420 int rdepth = 0;
1421 int class = 0;
1422 int rdepth_next;
1423 int class_next;
1424 int file_class_next;
1425
1426 int checked_flag = S_FALSE;
1427 int cchecked_flag = S_FALSE;
1428
1429 dirstack_t * dst_ptr;
1430
1431 int hardlink_num = 0;
1432
1433
1434 SL_ENTER(_("sh_files_checkdir"));
1435
1436 if (sig_urgent > 0) {
1437 SL_RETURN((0), _("sh_files_checkdir"));
1438 }
1439
1440 if (iname == NULL || idepth < (-1))
1441 SL_RETURN((-1), _("sh_files_checkdir"));
1442
1443 if (idepth < 0)
1444 {
1445 /* hash_remove_tree (iname); */
1446 SL_RETURN((0), _("sh_files_checkdir"));
1447 }
1448
1449 rdepth = idepth;
1450 class = iclass;
1451
1452 tmpname = sh_util_safe_name (iname);
1453
1454 /* ---- check for obscure name ----
1455 */
1456 if (iclass != SH_LEVEL_ALLIGNORE)
1457 {
1458 sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], iname, S_TRUE);
1459 }
1460
1461 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK,
1462 tmpname);
1463
1464 /* ---- check input ----
1465 */
1466 if ( sl_strlen(iname) >= PATH_MAX)
1467 {
1468 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1469 MSG_FI_2LONG,
1470 tmpname);
1471 SH_FREE(tmpname);
1472 SL_RETURN((-1), _("sh_files_checkdir"));
1473 }
1474
1475 /* ---- check for absolute path ---- */
1476 if ( iname[0] != '/')
1477 {
1478 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1479 MSG_FI_NOPATH,
1480 tmpname);
1481 SH_FREE(tmpname);
1482 SL_RETURN((-1), _("sh_files_checkdir"));
1483 }
1484
1485
1486 /* ---- stat the directory ----
1487 */
1488 sl_strlcpy (theFile.fullpath, iname, PATH_MAX);
1489
1490 (void) relativeName;
1491 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_DIR],
1492 iname,
1493 &theFile, NULL, iclass);
1494
1495 if ((sig_termfast == 1) || (sig_terminate == 1))
1496 {
1497 SL_RETURN((0), _("sh_files_checkdir"));
1498 }
1499
1500 if (status == -1)
1501 {
1502 SH_FREE(tmpname);
1503 SL_RETURN((-1), _("sh_files_checkdir"));
1504 }
1505
1506 if (theFile.c_mode[0] != 'd')
1507 {
1508 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1509 MSG_FI_NODIR,
1510 tmpname);
1511 SH_FREE(tmpname);
1512 SL_RETURN((-1), _("sh_files_checkdir"));
1513 }
1514
1515 hardlink_num = theFile.hardlinks;
1516
1517
1518 /* ---- open directory for reading ----
1519 *
1520 * opendir() will fail with ENOTDIR if the path has been changed
1521 * to a non-directory in between lstat() and opendir().
1522 */
1523 thisDir = opendir (iname);
1524
1525 if (thisDir == NULL)
1526 {
1527 status = errno;
1528 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1529 MSG_E_OPENDIR,
1530 sh_error_message (status), tmpname);
1531 SH_FREE(tmpname);
1532
1533 SL_RETURN((-1), _("sh_files_checkdir"));
1534 }
1535
1536 theDir.NumRegular = 0;
1537 theDir.NumDirs = 0;
1538 theDir.NumSymlinks = 0;
1539 theDir.NumFifos = 0;
1540 theDir.NumSockets = 0;
1541 theDir.NumCDev = 0;
1542 theDir.NumBDev = 0;
1543 theDir.NumAll = 0;
1544 theDir.TotalBytes = 0;
1545 sl_strlcpy (theDir.DirPath, iname, PATH_MAX);
1546
1547
1548 /* ---- read ----
1549 */
1550 do {
1551 thisEntry = readdir (thisDir);
1552 if (thisEntry != NULL)
1553 {
1554 ++theDir.NumAll;
1555 if (sl_strcmp (thisEntry->d_name, ".") == 0)
1556 {
1557 ++theDir.NumDirs;
1558 continue;
1559 }
1560 if (sl_strcmp (thisEntry->d_name, "..") == 0)
1561 {
1562 ++theDir.NumDirs;
1563 continue;
1564 }
1565 dirlist = addto_sh_dirlist (thisEntry, dirlist);
1566 }
1567 } while (thisEntry != NULL);
1568
1569 closedir (thisDir);
1570
1571 ++sh.statistics.dirs_checked;
1572
1573 dirlist_orig = dirlist;
1574
1575 do {
1576
1577 /* If the directory is empty, dirlist = NULL
1578 */
1579 if (!dirlist)
1580 break;
1581
1582 if (sig_termfast == 1)
1583 {
1584 SL_RETURN((0), _("sh_files_checkdir"));
1585 }
1586
1587 BREAKEXIT(sh_derr);
1588 if (0 == (rand() % 5))
1589 (void) sh_derr();
1590
1591 /* ---- Check the file. ----
1592 */
1593 tmpcat = SH_ALLOC(PATH_MAX);
1594 sl_strlcpy(tmpcat, iname, PATH_MAX);
1595 if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/')
1596 sl_strlcat(tmpcat, "/", PATH_MAX);
1597 sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX);
1598
1599 rdepth_next = rdepth - 1;
1600 class_next = class;
1601 file_class_next = class;
1602 checked_flag = -1;
1603 cchecked_flag = -1;
1604
1605 /* Wed Aug 24 2005 compare against dirListOne, dirListTwo
1606 * this fixes the problem that the directory special file
1607 * is checked with the policy of the parent directory
1608 */
1609 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
1610
1611 if (dst_ptr)
1612 {
1613 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
1614 * this fixes the problem that a policy for the directory
1615 * inode erroneously becomes a policy for the directory itself.
1616 */
1617 file_class_next = dst_ptr->class;
1618 checked_flag = dst_ptr->checked;
1619 cchecked_flag = dst_ptr->childs_checked;
1620 break;
1621 }
1622
1623 if (checked_flag == -1)
1624 {
1625 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
1626
1627 if (dst_ptr)
1628 {
1629 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
1630 * this fixes the problem that a policy for the directory
1631 * inode erroneously becomes a policy for the directory itself.
1632 */
1633 file_class_next = dst_ptr->class;
1634 checked_flag = dst_ptr->checked;
1635 cchecked_flag = dst_ptr->childs_checked;
1636 break;
1637 }
1638 }
1639
1640 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
1641
1642 if (dst_ptr)
1643 {
1644 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
1645 * this fixes the problem that a policy for the directory
1646 * inode erroneously becomes a policy for the directory itself.
1647 */
1648 file_class_next = dst_ptr->class;
1649 checked_flag = dst_ptr->checked;
1650 cchecked_flag = dst_ptr->childs_checked;
1651 break;
1652 }
1653
1654 /* ---- Has been checked already. ----
1655 */
1656 if (checked_flag == S_TRUE && cchecked_flag == S_TRUE)
1657 {
1658 /* Mar 11 2004 get ftype for complete directory count
1659 */
1660 checkit = sh_unix_get_ftype(tmpcat);
1661 if (checkit == SH_FILE_DIRECTORY)
1662 {
1663 ++theDir.NumDirs;
1664 }
1665 SH_FREE(tmpcat);
1666 dirlist = dirlist->next;
1667 continue;
1668 }
1669
1670 /* --- May be true, false, or not found. ---
1671 */
1672 if (checked_flag == S_TRUE)
1673 {
1674 /* -- need only the file type --
1675 */
1676 checkit = sh_unix_get_ftype(tmpcat);
1677 }
1678 else
1679 {
1680 /* -- need to check the file itself --
1681 */
1682 if (dst_ptr && sh.flag.reportonce == S_TRUE)
1683 dummy = dst_ptr->reported;
1684
1685 checkit = sh_files_filecheck (file_class_next,
1686 iname,
1687 dirlist->sh_d_name,
1688 &dummy, 0);
1689
1690 if (dst_ptr && checked_flag == S_FALSE)
1691 dst_ptr->checked = S_TRUE;
1692 /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag
1693 */
1694 if (dst_ptr && sh.flag.reportonce == S_TRUE)
1695 dst_ptr->reported = dummy;
1696 }
1697
1698 if (checkit == SH_FILE_REGULAR)
1699 ++theDir.NumRegular;
1700
1701 else if (checkit == SH_FILE_DIRECTORY)
1702 {
1703 ++theDir.NumDirs;
1704 if (rdepth_next >= 0 && cchecked_flag != S_TRUE)
1705 {
1706 rdepth_next = rdepth - 1;
1707
1708 /* check whether the new directory is in the
1709 * list with a recursion depth already defined
1710 */
1711 checked_flag = -1;
1712 cchecked_flag = -1;
1713
1714 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
1715
1716 if (dst_ptr)
1717 {
1718 TPT((0, FIL__, __LINE__,
1719 _("msg=<%s -> recursion depth %d\n>"),
1720 dst_ptr->name, dst_ptr->rdepth));
1721 rdepth_next = dst_ptr->rdepth;
1722 class_next = dst_ptr->class;
1723 /* 28. Aug 2001 reversed
1724 */
1725 cchecked_flag = dst_ptr->childs_checked;
1726 checked_flag = dst_ptr->checked;
1727 break;
1728 }
1729
1730 if (checked_flag == -1)
1731 {
1732 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
1733
1734 if (dst_ptr)
1735 {
1736 TPT((0, FIL__, __LINE__,
1737 _("msg=<%s -> recursion depth %d\n>"),
1738 dst_ptr->name, dst_ptr->rdepth));
1739 rdepth_next = dst_ptr->rdepth;
1740 class_next = dst_ptr->class;
1741 /* 28. Aug 2001 reversed
1742 */
1743 cchecked_flag = dst_ptr->childs_checked;
1744 checked_flag = dst_ptr->checked;
1745 break;
1746 }
1747 }
1748
1749 if (cchecked_flag == S_FALSE)
1750 {
1751 sh_files_checkdir (class_next, rdepth_next, tmpcat,
1752 dirlist->sh_d_name);
1753 dst_ptr->childs_checked = S_TRUE;
1754 }
1755 else if (checked_flag == -1)
1756 sh_files_checkdir (class_next, rdepth_next, tmpcat,
1757 dirlist->sh_d_name);
1758
1759 }
1760 }
1761
1762 else if (checkit == SH_FILE_SYMLINK) ++theDir.NumSymlinks;
1763 else if (checkit == SH_FILE_FIFO) ++theDir.NumFifos;
1764 else if (checkit == SH_FILE_SOCKET) ++theDir.NumSockets;
1765 else if (checkit == SH_FILE_CDEV) ++theDir.NumCDev;
1766 else if (checkit == SH_FILE_BDEV) ++theDir.NumBDev;
1767
1768 SH_FREE(tmpcat);
1769
1770 if ((sig_termfast == 1) || (sig_terminate == 1))
1771 {
1772 SL_RETURN((0), _("sh_files_checkdir"));
1773 }
1774
1775 dirlist = dirlist->next;
1776
1777 } while (dirlist != NULL);
1778
1779 if (flag_err_info == SL_TRUE)
1780 {
1781 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
1782 theDir.NumDirs,
1783 theDir.NumRegular,
1784 theDir.NumSymlinks,
1785 theDir.NumFifos,
1786 theDir.NumSockets,
1787 theDir.NumCDev,
1788 theDir.NumBDev);
1789 }
1790
1791 kill_sh_dirlist (dirlist_orig);
1792
1793#if !defined(HOST_IS_DARWIN)
1794 /*
1795 * Hardlink check; not done on MacOS X because of resource forks
1796 */
1797 if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir.NumDirs))
1798 {
1799 if (0 != sh_files_hle_test(hardlink_num-theDir.NumDirs, iname))
1800 {
1801 tmpcat = SH_ALLOC(strlen(tmpname) + 256);
1802 sl_snprintf(tmpcat, strlen(tmpname) + 256,
1803 _("%s: subdirectory count (%d) != hardlinks (%d)"),
1804 tmpname, theDir.NumDirs, hardlink_num);
1805 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1806 MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir"));
1807 SH_FREE(tmpcat);
1808 }
1809 }
1810#endif
1811
1812 SH_FREE(tmpname);
1813
1814 SL_RETURN((0), _("sh_files_checkdir"));
1815}
1816
1817int get_the_fd (SL_TICKET ticket);
1818
1819
1820static ShFileType sh_files_filecheck (int class, char * dirName,
1821 char * fileName,
1822 int * reported,
1823 int rsrcflag)
1824{
1825 /* 28 Aug 2001 allow NULL fileName
1826 */
1827 char fullpath[PATH_MAX];
1828 char fileHash[KEY_LEN + 1];
1829 int status;
1830 file_type theFile;
1831 char * tmpdir;
1832 char * tmpname;
1833 struct utimbuf utime_buf;
1834
1835 SL_ENTER(_("sh_files_filecheck"));
1836
1837 BREAKEXIT(sh_derr);
1838 if (0 == (rand() % 2))
1839 (void) sh_derr();
1840
1841 /* fileName may be NULL if this is a directory
1842 */
1843 if (dirName == NULL /* || fileName == NULL */)
1844 {
1845 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL);
1846 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
1847 }
1848
1849 if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) &&
1850 (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME],
1851 fileName, S_FALSE)))
1852 {
1853 if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0'))
1854 {
1855 tmpname = sh_util_safe_name (fileName);
1856 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
1857 MSG_FI_OBSC2,
1858 "", tmpname);
1859 SH_FREE(tmpname);
1860 }
1861 else
1862 {
1863 tmpdir = sh_util_safe_name (dirName);
1864 tmpname = sh_util_safe_name (fileName);
1865 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
1866 MSG_FI_OBSC2,
1867 tmpdir, tmpname);
1868 SH_FREE(tmpname);
1869 SH_FREE(tmpdir);
1870 }
1871 }
1872
1873 /* sh_files_fullpath accepts NULL fileName
1874 */
1875 if (0 != sh_files_fullpath (dirName, fileName, fullpath))
1876 {
1877 tmpdir = sh_util_safe_name (dirName);
1878 tmpname = sh_util_safe_name (fileName);
1879 sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0,
1880 MSG_FI_2LONG2,
1881 tmpdir, tmpname);
1882 SH_FREE(tmpname);
1883 SH_FREE(tmpdir);
1884 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
1885 }
1886
1887
1888 /* stat the file and determine checksum (if a regular file)
1889 */
1890 sl_strlcpy (theFile.fullpath, fullpath, PATH_MAX);
1891 theFile.check_mask = sh_files_maskof(class);
1892 theFile.reported = (*reported);
1893
1894 TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"), fullpath));
1895
1896 status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ?
1897 ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE],
1898 fileName,
1899 &theFile, fileHash, class);
1900
1901 if (status != 0)
1902 {
1903 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
1904 fullpath, status));
1905 if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
1906 sh_hash_set_visited_true (fullpath);
1907 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
1908 }
1909
1910 if (sig_termfast == 1) {
1911 goto ret_point;
1912 }
1913
1914 /* report
1915 */
1916 if ((flag_err_debug == SL_TRUE) && (theFile.c_mode[0] == '-'))
1917 {
1918 tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
1919 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM,
1920 fileHash, tmpname);
1921 SH_FREE(tmpname);
1922 }
1923 ++sh.statistics.files_checked;
1924
1925 if ( sh.flag.checkSum == SH_CHECK_INIT && sh.flag.update == S_FALSE )
1926 {
1927 sh_hash_pushdata (&theFile, fileHash);
1928 }
1929 else if (sh.flag.checkSum == SH_CHECK_INIT && sh.flag.update == S_TRUE )
1930 {
1931 if (0 == sh_hash_compdata (class, &theFile, fileHash, NULL, -1))
1932 {
1933 sh_hash_pushdata (&theFile, fileHash);
1934 }
1935 }
1936 else if (sh.flag.checkSum == SH_CHECK_CHECK
1937 /* && theFile.c_mode[0] == '-' */
1938 /* && class != SH_LEVEL_ALLIGNORE */
1939 )
1940 {
1941 sh_hash_compdata (class, &theFile, fileHash, NULL, -1);
1942 }
1943
1944 (*reported) = theFile.reported;
1945
1946 /* reset the access time
1947 */
1948 if (class == SH_LEVEL_NOIGNORE && (theFile.check_mask & MODI_ATM) != 0)
1949 {
1950 utime_buf.actime = (time_t) theFile.atime;
1951 utime_buf.modtime = (time_t) theFile.mtime;
1952#if !defined(O_NOATIME)
1953 retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf);
1954#endif
1955 }
1956
1957#ifdef HOST_IS_DARWIN
1958 /*
1959 * Check for resource fork
1960 */
1961 if ( (theFile.c_mode[0] != 'd') && (rsrcflag == 0) )
1962 {
1963 int dummy;
1964 static int rsrc_init = 0;
1965 static char rsrc[17];
1966 char testpath[PATH_MAX];
1967
1968 if (rsrc_init == 0) {
1969 sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17);
1970 rsrc_init = 1;
1971 }
1972 sl_strlcpy (testpath, fullpath, PATH_MAX);
1973 sl_strlcat (testpath, "/", PATH_MAX);
1974 sl_strlcat (testpath, rsrc, PATH_MAX);
1975
1976 if (sl_strlen(testpath) == (17 + sl_strlen(fullpath)))
1977 {
1978 if (0 == sh_unix_file_stat (testpath))
1979 {
1980 sh_files_filecheck (class, fullpath, rsrc, &dummy, 1);
1981 }
1982 }
1983 }
1984#else
1985 (void) rsrcflag; /* avoid compiler warning */
1986#endif
1987
1988 ret_point:
1989
1990 switch (theFile.c_mode[0])
1991 {
1992 case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck"));
1993 case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck"));
1994 case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck"));
1995 case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck"));
1996 case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck"));
1997 case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck"));
1998 case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck"));
1999 default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2000 }
2001
2002 /* notreached */
2003}
2004
2005/* concatenate statpath = testdir"/"d_name
2006 */
2007static int sh_files_fullpath (char * testdir, char * d_name, char * statpath)
2008{
2009 int llen = 0;
2010
2011 SL_ENTER(_("sh_files_fullpath"));
2012
2013 if (testdir != NULL)
2014 {
2015 if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) )
2016 SL_RETURN((-1),_("sh_files_fullpath"));
2017 sl_strlcpy(statpath, testdir, PATH_MAX - 1);
2018 }
2019 if (d_name != NULL)
2020 {
2021 if (llen > 1 || statpath[0] != '/')
2022 sl_strlcat(statpath, "/", PATH_MAX);
2023 if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX)
2024 SL_RETURN((-1),_("sh_files_fullpath"));
2025 sl_strlcat(statpath, d_name, PATH_MAX);
2026 }
2027 if (statpath == NULL)
2028 SL_RETURN((-1),_("sh_files_fullpath"));
2029 SL_RETURN((0),_("sh_files_fullpath"));
2030}
2031
2032
2033/* -----------------------------------
2034 *
2035 * The following two routines serve to
2036 * verify that the user has selected
2037 * a proper setup for file policies.
2038 *
2039 * -----------------------------------
2040 */
2041static int check_file(char * name)
2042{
2043 dirstack_t * pfilL;
2044 zAVLCursor cursor;
2045
2046 SL_ENTER(_("check_file"));
2047
2048 if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name))
2049 SL_RETURN(0, _("check_file"));
2050
2051 for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL;
2052 pfilL = (dirstack_t *) zAVLNext (&cursor))
2053 {
2054 if (0 == strcmp(name, pfilL->name) &&
2055 (pfilL->check_mask & MODI_ATM) == 0 &&
2056 (pfilL->check_mask & MODI_CTM) == 0 &&
2057 (pfilL->check_mask & MODI_MTM) == 0)
2058 SL_RETURN(0, _("check_file"));
2059 }
2060 SL_RETURN((-1), _("check_file"));
2061}
2062
2063int sh_files_test_setup_int (zAVLTree * tree)
2064{
2065 int dlen, flen;
2066 zAVLCursor cursor1;
2067 zAVLCursor cursor2;
2068
2069 dirstack_t * pdirL;
2070 dirstack_t * pfilL;
2071
2072 SL_ENTER(_("sh_files_test_setup"));
2073
2074 for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL;
2075 pdirL = (dirstack_t *) zAVLNext (&cursor1))
2076 {
2077 dlen = strlen(pdirL->name);
2078
2079 for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL;
2080 pfilL = (dirstack_t *) zAVLNext (&cursor2))
2081 {
2082 flen = strlen(pfilL->name);
2083
2084 /* check whether file is in tree of dir
2085 */
2086 if ((pfilL->class == SH_LEVEL_READONLY) ||
2087 (pfilL->class == SH_LEVEL_NOIGNORE))
2088 {
2089 ; /* do nothing */
2090 }
2091 else
2092 {
2093 if ((flen > (dlen+1)) &&
2094 (pfilL->name[dlen] == '/') &&
2095 (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/
2096 (0 == strncmp(pfilL->name, pdirL->name, dlen)))
2097 {
2098 if ((pdirL->check_mask & MODI_ATM) != 0 ||
2099 (pdirL->check_mask & MODI_MTM) != 0 ||
2100 (pdirL->check_mask & MODI_CTM) != 0)
2101 {
2102 if (check_file (pdirL->name) != 0)
2103 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL,
2104 pdirL->name, pfilL->name);
2105 }
2106 }
2107 }
2108 }
2109 }
2110
2111 SL_RETURN((0), _("sh_files_test_setup"));
2112}
2113
2114int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList)
2115{
2116 int count;
2117 int retval = 0;
2118
2119 zAVLCursor cursor;
2120
2121 dirstack_t * first;
2122
2123 for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first;
2124 first = (dirstack_t *) zAVLNext (&cursor))
2125 {
2126
2127 if (NULL != zAVLSearch(secondList, first->name))
2128 {
2129 ++count;
2130 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
2131 first->name);
2132 retval = 1;
2133 }
2134 }
2135 return retval;
2136}
2137
2138extern void aud_exit (char * file, int line, int fd);
2139
2140int sh_files_test_setup ()
2141{
2142 int retval = 0;
2143
2144 /* Test for modifications allowed in ReadOnly directory
2145 */
2146 sh_files_test_setup_int (zdirListOne);
2147 sh_files_test_setup_int (zdirListTwo);
2148
2149 /* Test for files/dirz defined twice
2150 */
2151 retval = sh_files_test_double (zdirListOne, zdirListTwo);
2152 if (retval != 0)
2153 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2154
2155 retval = sh_files_test_double (zdirListTwo, zdirListOne);
2156 if (retval != 0)
2157 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2158
2159 /*
2160 retval = sh_files_test_double (zfileList, NULL);
2161 if (retval != 0)
2162 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2163 */
2164 return 0;
2165}
2166
2167#endif
Note: See TracBrowser for help on using the repository browser.