source: trunk/src/sh_files.c@ 11

Last change on this file since 11 was 8, checked in by rainer, 19 years ago

minor optimisations for speed

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