source: trunk/src/sh_files.c@ 365

Last change on this file since 365 was 365, checked in by katerina, 13 years ago

Fix for ticket #269 (Issue with redefinition of policies).

File size: 65.6 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <ctype.h>
26#include <limits.h>
27
28#include <errno.h>
29
30/* Must be before <utime.h> on FreeBSD
31 */
32#include <sys/types.h>
33#include <unistd.h>
34
35#include <utime.h>
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#define NEED_ADD_DIRENT
54
55#ifdef HAVE_GLOB_H
56#include <glob.h>
57#endif
58
59#include "samhain.h"
60
61#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
62
63#include "sh_pthread.h"
64#include "sh_error.h"
65#include "sh_utils.h"
66#include "sh_unix.h"
67#include "sh_files.h"
68#include "sh_tiger.h"
69#include "sh_hash.h"
70#include "sh_ignore.h"
71#include "zAVLTree.h"
72
73#undef FIL__
74#define FIL__ _("sh_files.c")
75
76static char * sh_files_C_dequote (char * s, size_t * length)
77{
78 size_t i, len = *length;
79 int flag = 0;
80 char *p, *q, *po, *pend;
81
82 /* search for backslash
83 */
84 for (i = 0; i < len; ++i)
85 {
86 if (s[i] == '\\')
87 {
88 flag = 1;
89 break;
90 }
91 }
92
93 if (flag == 0 || *s == '\0')
94 return s;
95
96 po = SH_ALLOC(len+1); *po = '\0'; p = po; pend = &po[len];
97
98 i = 0; q = s;
99
100 do
101 {
102 if (*q == '\\')
103 {
104 ++q;
105
106 if (*q == '\0')
107 { *p = *q; flag = 0; break; }
108 else if (*q == 'a')
109 { *p = '\a'; ++p; ++q; }
110 else if (*q == 'b')
111 { *p = '\b'; ++p; ++q; }
112 else if (*q == 'f')
113 { *p = '\f'; ++p; ++q; }
114 else if (*q == 'n')
115 { *p = '\n'; ++p; ++q; }
116 else if (*q == 'r')
117 { *p = '\r'; ++p; ++q; }
118 else if (*q == 't')
119 { *p = '\t'; ++p; ++q; }
120 else if (*q == 'v')
121 { *p = '\v'; ++p; ++q; }
122 else if (*q == '\\')
123 { *p = '\\'; ++p; ++q; }
124 else if (*q == '\'')
125 { *p = '\''; ++p; ++q; }
126 else if (*q == '"')
127 { *p = '"'; ++p; ++q; }
128 else if (*q == 'x')
129 {
130 if (isxdigit((int) q[1]) && isxdigit((int) q[2]))
131 {
132 /* hexadecimal value following */
133 unsigned char cc = (16 * sh_util_hexchar(q[1]))
134 + sh_util_hexchar(q[2]);
135 *p = (char) cc;
136 ++p; q += 3;
137 }
138 else
139 {
140 *p = '\0'; flag = 0; break;
141 }
142 }
143 else if (isdigit((int)*q))
144 {
145 if (isdigit((int) q[1]) && q[1] < '8' &&
146 isdigit((int) q[2]) && q[2] < '8')
147 {
148 /* octal value following */
149 char tmp[4]; unsigned char cc;
150 tmp[0] = *q; ++q; tmp[1] = *q; ++q; tmp[2] = *q; ++q;
151 tmp[3] = '\0';
152 cc = strtol(tmp, NULL, 8);
153 *p = (char) cc; ++p;
154 }
155 else
156 {
157 *p = '\0'; flag = 0; break;
158 }
159 }
160 else
161 {
162 /* invalid escape sequence */
163 *p = '\0'; flag = 0; break;
164 }
165 }
166 else
167 {
168 *p = *q;
169 ++p; ++q;
170 }
171 } while (*q && p <= pend);
172
173 SL_REQUIRE (p <= pend, _("p <= pend"));
174
175 if (flag)
176 {
177 *p = '\0';
178 *length = strlen(po);
179 }
180 else
181 {
182 SH_FREE(po);
183 po = NULL;
184 *length = 0;
185 }
186
187 SL_REQUIRE (*length <= len, _("*length <= len"));
188
189 SH_FREE(s);
190 return po;
191}
192
193extern int flag_err_debug;
194extern int flag_err_info;
195
196int sh_files_reportonce(const char * c)
197{
198 int i;
199 SL_ENTER(_("sh_files_reportonce"));
200 i = sh_util_flagval(c, &(sh.flag.reportonce));
201
202 SL_RETURN(i, _("sh_files_reportonce"));
203}
204
205int sh_files_fulldetail(const char * c)
206{
207 int i;
208 SL_ENTER(_("sh_files_fulldetail"));
209 i = sh_util_flagval(c, &(sh.flag.fulldetail));
210
211 SL_RETURN((i), _("sh_files_fulldetail"));
212}
213
214
215typedef struct dir_struct {
216 long NumRegular;
217 long NumDirs;
218 long NumSymlinks;
219 long NumFifos;
220 long NumSockets;
221 long NumCDev;
222 long NumBDev;
223 long NumDoor;
224 long NumPort;
225 long NumAll;
226 long TotalBytes;
227 char DirPath[PATH_MAX];
228} dir_type;
229
230typedef struct dirstack_entry {
231 char * name;
232 int class;
233 unsigned long check_mask;
234 int rdepth;
235 short checked;
236 short childs_checked;
237 short is_reported;
238 /* struct dirstack_entry * next; */
239} dirstack_t;
240
241
242/* the destructor
243 */
244void free_dirstack (void * inptr)
245{
246 dirstack_t * here;
247
248 SL_ENTER(_("free_dirstack"));
249 if (inptr == NULL)
250 SL_RET0(_("free_dirstack"));
251 else
252 here = (dirstack_t *) inptr;
253
254 if (here->name != NULL)
255 SH_FREE(here->name);
256 SH_FREE(here);
257 SL_RET0(_("free_dirstack"));
258}
259
260/* Function to return the key for indexing
261 * the argument
262 */
263zAVLKey zdirstack_key (void const * arg)
264{
265 const dirstack_t * sa = (const dirstack_t *) arg;
266 return (zAVLKey) sa->name;
267}
268
269#define SH_LIST_FILE 0
270#define SH_LIST_DIR1 1
271#define SH_LIST_DIR2 2
272
273
274static int which_dirList = SH_LIST_DIR1;
275
276static zAVLTree * zdirListOne = NULL;
277static zAVLTree * zdirListTwo = NULL;
278static zAVLTree * zfileList = NULL;
279
280
281static int sh_files_fullpath (char * testdir, char * d_name,
282 char * statpath);
283static int sh_files_pushdir (int class, const char * str_s);
284static int sh_files_pushfile (int class, const char * str_s);
285static int sh_files_checkdir (int class, unsigned long check_mask,
286 int rdepth, char * dirName,
287 char * relativeName);
288
289static long MaxRecursionLevel = 0;
290
291/* set default recursion level
292 */
293int sh_files_setrecursion (const char * flag_s)
294{
295 long flag = 0;
296 static int reject = 0;
297
298 SL_ENTER( _("sh_files_setrecursion"));
299
300 if (reject == 1)
301 SL_RETURN((-1), _("sh_files_setrecursion"));
302
303 if (sh.flag.opts == 1)
304 reject = 1;
305
306 if (flag_s != NULL)
307 flag = (int)(atof(flag_s));
308
309 if (flag >= 0 && flag <= 99)
310 MaxRecursionLevel = flag;
311 else
312 SL_RETURN((-1), _("sh_files_setrecursion"));
313
314 SL_RETURN((0), _("sh_files_setrecursion"));
315}
316
317unsigned long sh_files_chk ()
318{
319 zAVLCursor cursor;
320 ShFileType status;
321 unsigned long fcount = 0;
322
323 char * tmp = NULL;
324
325 dirstack_t * ptr;
326 char * dir;
327 char * file;
328 int tmp_reported;
329
330 SL_ENTER(_("sh_files_chk"));
331
332 for (ptr = (dirstack_t *) zAVLFirst(&cursor, zfileList); ptr;
333 ptr = (dirstack_t *) zAVLNext(&cursor))
334 {
335
336 if (sig_urgent > 0) {
337 SL_RETURN(fcount, _("sh_files_chk"));
338 }
339
340 if (ptr->checked == S_FALSE)
341 {
342 dir = sh_util_dirname (ptr->name);
343 file = sh_util_basename (ptr->name);
344#if defined(WITH_TPT)
345 tmp = sh_util_safe_name (ptr->name);
346#endif
347
348
349 if (flag_err_info == SL_TRUE)
350 {
351 char pstr[32];
352#if !defined(WITH_TPT)
353 tmp = sh_util_safe_name (ptr->name);
354#endif
355 sl_strlcpy(pstr, sh_hash_getpolicy(ptr->class), sizeof(pstr));
356 sh_error_handle ((-1), FIL__, __LINE__, 0,
357 MSG_FI_CHK, pstr, tmp);
358 }
359
360 BREAKEXIT(sh_files_filecheck);
361 tmp_reported = ptr->is_reported; /* fix aliasing warning */
362 status = sh_files_filecheck (ptr->class, ptr->check_mask, dir, file,
363 &tmp_reported, 0);
364 ptr->is_reported = tmp_reported;
365
366 TPT(( 0, FIL__, __LINE__,
367 _("msg=<filecheck complete: %s> status=<%d> reported=<%d>\n"),
368 tmp, status, ptr->is_reported));
369
370 if (status == SH_FILE_UNKNOWN && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
371 {
372 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
373 tmp, status));
374
375 if ( sh.flag.checkSum == SH_CHECK_INIT ||
376 sh_hash_have_it (ptr->name) >= 0)
377 {
378 if (S_FALSE == sh_ignore_chk_del(ptr->name))
379 {
380 if (0 != hashreport_missing(ptr->name,
381 (ptr->class == SH_LEVEL_ALLIGNORE) ?
382 ShDFLevel[ptr->class] :
383 ShDFLevel[SH_ERR_T_FILE])) {
384 if (tmp == NULL)
385 tmp = sh_util_safe_name (ptr->name);
386 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
387 ShDFLevel[ptr->class] :
388 ShDFLevel[SH_ERR_T_FILE],
389 FIL__, __LINE__, 0, MSG_FI_MISS,
390 tmp);
391 }
392 }
393 }
394 else /* not there at init, and still missing */
395 {
396 if (tmp == NULL)
397 tmp = sh_util_safe_name (ptr->name);
398 sh_error_handle (SH_ERR_NOTICE,
399 FIL__, __LINE__, 0,
400 MSG_FI_FAIL,
401 tmp);
402 }
403#ifndef REPLACE_OLD
404 /* this will tell that we have seen the file, and thus prevent
405 * deletion from the database, resulting in an incomplete
406 * message when the file reappears
407 */
408 if (sh.flag.checkSum != SH_CHECK_INIT)
409 sh_hash_set_visited_true(ptr->name);
410#else
411 if (sh.flag.checkSum != SH_CHECK_INIT)
412 sh_hash_set_missing(ptr->name);
413#endif
414 if (sh.flag.reportonce == S_TRUE)
415 SET_SH_FFLAG_REPORTED(ptr->is_reported);
416 }
417 else
418 {
419 /* exists (status >= 0), but was missing (reported == TRUE)
420 */
421 if (status != SH_FILE_UNKNOWN && SH_FFLAG_REPORTED_SET(ptr->is_reported))
422 {
423 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
424 }
425 /* Catchall
426 */
427 else if (status == SH_FILE_UNKNOWN)
428 {
429 /* Thu Mar 7 15:09:40 CET 2002 Make sure missing file
430 * is reported if ptr->reported == S_TRUE because the
431 * file has been added.
432 */
433 if (sh_hash_have_it (ptr->name) >= 0 &&
434 !SH_FFLAG_REPORTED_SET(ptr->is_reported))
435 {
436 if (S_FALSE == sh_ignore_chk_del(ptr->name))
437 {
438 if (0 != hashreport_missing(ptr->name,
439 (ptr->class == SH_LEVEL_ALLIGNORE) ?
440 ShDFLevel[ptr->class] :
441 ShDFLevel[SH_ERR_T_FILE])) {
442 if (tmp == NULL)
443 tmp = sh_util_safe_name (ptr->name);
444 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE)?
445 ShDFLevel[ptr->class] :
446 ShDFLevel[SH_ERR_T_FILE],
447 FIL__, __LINE__, 0, MSG_FI_MISS,
448 tmp);
449 }
450 }
451#ifndef REPLACE_OLD
452 if (sh.flag.checkSum != SH_CHECK_INIT)
453 sh_hash_set_visited_true(ptr->name);
454#else
455 /* delete from database
456 */
457 if (sh.flag.checkSum != SH_CHECK_INIT)
458 sh_hash_set_missing(ptr->name);
459#endif
460 }
461 else
462 {
463 if (tmp == NULL)
464 tmp = sh_util_safe_name (ptr->name);
465 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
466 MSG_FI_FAIL,
467 tmp);
468 if (sh.flag.checkSum != SH_CHECK_INIT)
469 sh_hash_set_visited_true(ptr->name);
470 }
471 }
472 ++fcount;
473 }
474
475 if (tmp != NULL)
476 {
477 SH_FREE(tmp);
478 tmp = NULL;
479 }
480 if (file)
481 SH_FREE(file);
482 if (dir)
483 SH_FREE(dir);
484
485 ptr->checked = S_TRUE;
486 }
487 }
488
489 SL_RETURN(fcount, _("sh_files_chk"));
490}
491
492int sh_files_delfilestack ()
493{
494 SL_ENTER(_("sh_files_delfilestack"));
495
496 zAVLFreeTree (zfileList, free_dirstack);
497 zfileList = NULL;
498
499 SL_RETURN(0, _("sh_files_delfilestack"));
500}
501
502int sh_files_setrec_int (zAVLTree * tree)
503{
504 dirstack_t * ptr;
505 zAVLCursor avlcursor;
506
507 SL_ENTER(_("sh_files_setrec"));
508 if (tree != NULL) {
509 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
510 ptr = (dirstack_t *) zAVLNext(&avlcursor))
511 {
512 if (ptr->rdepth < (-1) || ptr->rdepth > 99)
513 {
514 ptr->rdepth = MaxRecursionLevel;
515 }
516 if (ptr->rdepth == (-1) && sh.flag.checkSum != SH_CHECK_INIT)
517 hash_remove_tree (ptr->name);
518 }
519 }
520 SL_RETURN(0, _("sh_files_setrec"));
521}
522
523int sh_files_setrec ()
524{
525 sh_files_setrec_int(zdirListOne);
526 return sh_files_setrec_int(zdirListTwo);
527}
528
529zAVLTree * sh_files_deldirstack_int (zAVLTree * ptr)
530{
531 SL_ENTER(_("sh_files_deldirstack"));
532
533 zAVLFreeTree (ptr, free_dirstack);
534
535 SL_RETURN(NULL, _("sh_files_deldirstack"));
536}
537
538int sh_files_deldirstack ()
539{
540 zdirListOne = sh_files_deldirstack_int(zdirListOne);
541 zdirListTwo = sh_files_deldirstack_int(zdirListTwo);
542 return 0;
543}
544
545void sh_files_reset()
546{
547 dirstack_t * ptr;
548 zAVLCursor avlcursor;
549
550 SL_ENTER(_("sh_files_reset"));
551
552 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, zfileList); ptr;
553 ptr = (dirstack_t *) zAVLNext(&avlcursor))
554 ptr->checked = 0;
555
556 SL_RET0(_("sh_files_reset"));
557}
558
559void sh_dirs_reset()
560{
561 dirstack_t * ptr;
562 zAVLCursor avlcursor1;
563 zAVLCursor avlcursor2;
564
565 SL_ENTER(_("sh_dirs_reset"));
566
567 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor1, zdirListOne); ptr;
568 ptr = (dirstack_t *) zAVLNext(&avlcursor1))
569 ptr->checked = 0;
570
571 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor2, zdirListTwo); ptr;
572 ptr = (dirstack_t *) zAVLNext(&avlcursor2))
573 ptr->checked = 0;
574
575 SL_RET0(_("sh_dirs_reset"));
576}
577
578
579int sh_files_pushfile_prelink (const char * str_s)
580{
581 return (sh_files_pushfile (SH_LEVEL_PRELINK, str_s));
582}
583
584int sh_files_pushfile_user0 (const char * str_s)
585{
586 return (sh_files_pushfile (SH_LEVEL_USER0, str_s));
587}
588
589int sh_files_pushfile_user1 (const char * str_s)
590{
591 return (sh_files_pushfile (SH_LEVEL_USER1, str_s));
592}
593
594int sh_files_pushfile_user2 (const char * str_s)
595{
596 return (sh_files_pushfile (SH_LEVEL_USER2, str_s));
597}
598
599int sh_files_pushfile_user3 (const char * str_s)
600{
601 return (sh_files_pushfile (SH_LEVEL_USER3, str_s));
602}
603
604int sh_files_pushfile_user4 (const char * str_s)
605{
606 return (sh_files_pushfile (SH_LEVEL_USER4, str_s));
607}
608
609
610int sh_files_pushfile_ro (const char * str_s)
611{
612 return (sh_files_pushfile (SH_LEVEL_READONLY, str_s));
613}
614
615int sh_files_pushfile_attr (const char * str_s)
616{
617 return (sh_files_pushfile (SH_LEVEL_ATTRIBUTES, str_s));
618}
619
620int sh_files_pushfile_log (const char * str_s)
621{
622 return (sh_files_pushfile (SH_LEVEL_LOGFILES, str_s));
623}
624
625int sh_files_pushfile_glog (const char * str_s)
626{
627 return (sh_files_pushfile (SH_LEVEL_LOGGROW, str_s));
628}
629
630int sh_files_pushfile_noig (const char * str_s)
631{
632 return (sh_files_pushfile (SH_LEVEL_NOIGNORE, str_s));
633}
634
635int sh_files_pushfile_allig (const char * str_s)
636{
637 return (sh_files_pushfile (SH_LEVEL_ALLIGNORE, str_s));
638}
639
640
641static void sh_files_set_mask (unsigned long * mask,
642 unsigned long val, int act)
643{
644 SL_ENTER(_("sh_files_set_mask"));
645
646 if (act == 0)
647 (*mask) = val;
648 else if (act > 0)
649 (*mask) |= val;
650 else
651 (*mask) &= ~val;
652
653 SL_RET0(_("sh_files_set_mask"));
654}
655
656/* set mask(class)
657 */
658static int sh_files_parse_mask (unsigned long * mask, const char * str)
659{
660 int l, i = 0, act = 0, k = 0;
661 char myword[64];
662
663 SL_ENTER(_("sh_files_parse_mask"));
664
665 if (str == NULL)
666 {
667 SL_RETURN ( (-1), _("sh_files_parse_mask"));
668 }
669 else
670 l = sl_strlen(str);
671
672 while (i < l) {
673 if (str[i] == '\0')
674 break;
675 if (str[i] == ' ' || str[i] == '\t' || str[i] == ',')
676 {
677 ++i;
678 continue;
679 }
680
681 if (str[i] == '+')
682 {
683 act = +1; ++i;
684 continue;
685 }
686 else if (str[i] == '-')
687 {
688 act = -1; ++i;
689 continue;
690 }
691 else /* a word */
692 {
693 k = 0;
694 while (k < 63 && str[i] != ' ' && str[i] != '\t' && str[i] != ','
695 && str[i] != '+' && str[i] != '-' && str[i] != '\0') {
696 myword[k] = str[i];
697 ++i; ++k;
698 }
699 myword[k] = '\0';
700
701/* checksum */
702 if (0 == strncmp(myword, _("CHK"), 3))
703 sh_files_set_mask (mask, MODI_CHK, act);
704/* link */
705 if (0 == strncmp(myword, _("LNK"), 3))
706 sh_files_set_mask (mask, MODI_LNK, act);
707/* inode */
708 if (0 == strncmp(myword, _("RDEV"), 3))
709 sh_files_set_mask (mask, MODI_RDEV, act);
710/* inode */
711 if (0 == strncmp(myword, _("INO"), 3))
712 sh_files_set_mask (mask, MODI_INO, act);
713/* user */
714 if (0 == strncmp(myword, _("USR"), 3))
715 sh_files_set_mask (mask, MODI_USR, act);
716/* group */
717 if (0 == strncmp(myword, _("GRP"), 3))
718 sh_files_set_mask (mask, MODI_GRP, act);
719/* mtime */
720 if (0 == strncmp(myword, _("MTM"), 3))
721 sh_files_set_mask (mask, MODI_MTM, act);
722/* ctime */
723 if (0 == strncmp(myword, _("CTM"), 3))
724 sh_files_set_mask (mask, MODI_CTM, act);
725/* atime */
726 if (0 == strncmp(myword, _("ATM"), 3))
727 sh_files_set_mask (mask, MODI_ATM, act);
728/* size */
729 if (0 == strncmp(myword, _("SIZ"), 3))
730 sh_files_set_mask (mask, MODI_SIZ, act);
731/* file mode */
732 if (0 == strncmp(myword, _("MOD"), 3))
733 sh_files_set_mask (mask, MODI_MOD, act);
734/* hardlinks */
735 if (0 == strncmp(myword, _("HLN"), 3))
736 sh_files_set_mask (mask, MODI_HLN, act);
737/* size may grow */
738 if (0 == strncmp(myword, _("GROW"), 3))
739 sh_files_set_mask (mask, MODI_SGROW, act);
740/* use prelink */
741 if (0 == strncmp(myword, _("PRE"), 3))
742 sh_files_set_mask (mask, MODI_PREL, act);
743/* get content */
744 if (0 == strncmp(myword, _("TXT"), 3))
745 sh_files_set_mask (mask, MODI_TXT, act);
746/* get content */
747 if (0 == strncmp(myword, _("AUDIT"), 3))
748 sh_files_set_mask (mask, MODI_AUDIT, act);
749 }
750 }
751 SL_RETURN ( (0), _("sh_files_parse_mask"));
752}
753
754int sh_files_redef_prelink(const char * str)
755{
756 return (sh_files_parse_mask(&mask_PRELINK, str));
757}
758int sh_files_redef_user0(const char * str)
759{
760 return (sh_files_parse_mask(&mask_USER0, str));
761}
762int sh_files_redef_user1(const char * str)
763{
764 return (sh_files_parse_mask(&mask_USER1, str));
765}
766int sh_files_redef_user2(const char * str)
767{
768 return (sh_files_parse_mask(&mask_USER2, str));
769}
770int sh_files_redef_user3(const char * str)
771{
772 return (sh_files_parse_mask(&mask_USER3, str));
773}
774int sh_files_redef_user4(const char * str)
775{
776 return (sh_files_parse_mask(&mask_USER4, str));
777}
778int sh_files_redef_readonly(const char * str)
779{
780 return (sh_files_parse_mask(&mask_READONLY, str));
781}
782int sh_files_redef_loggrow(const char * str)
783{
784 return (sh_files_parse_mask(&mask_LOGGROW, str));
785}
786int sh_files_redef_logfiles(const char * str)
787{
788 return (sh_files_parse_mask(&mask_LOGFILES, str));
789}
790int sh_files_redef_attributes(const char * str)
791{
792 return (sh_files_parse_mask(&mask_ATTRIBUTES, str));
793}
794int sh_files_redef_noignore(const char * str)
795{
796 return (sh_files_parse_mask(&mask_NOIGNORE, str));
797}
798int sh_files_redef_allignore(const char * str)
799{
800 return (sh_files_parse_mask(&mask_ALLIGNORE, str));
801}
802
803unsigned long sh_files_maskof (int class)
804{
805 switch (class)
806 {
807 case SH_LEVEL_READONLY:
808 return (unsigned long) mask_READONLY;
809 case SH_LEVEL_ATTRIBUTES:
810 return (unsigned long) mask_ATTRIBUTES;
811 case SH_LEVEL_LOGFILES:
812 return (unsigned long) mask_LOGFILES;
813 case SH_LEVEL_LOGGROW:
814 return (unsigned long) mask_LOGGROW;
815 case SH_LEVEL_ALLIGNORE:
816 return (unsigned long) mask_ALLIGNORE;
817 case SH_LEVEL_NOIGNORE:
818 return (unsigned long) mask_NOIGNORE;
819 case SH_LEVEL_USER0:
820 return (unsigned long) mask_USER0;
821 case SH_LEVEL_USER1:
822 return (unsigned long) mask_USER1;
823 case SH_LEVEL_USER2:
824 return (unsigned long) mask_USER2;
825 case SH_LEVEL_USER3:
826 return (unsigned long) mask_USER3;
827 case SH_LEVEL_USER4:
828 return (unsigned long) mask_USER4;
829 case SH_LEVEL_PRELINK:
830 return (unsigned long) mask_PRELINK;
831 default:
832 return (unsigned long) 0;
833 }
834}
835
836#ifdef HAVE_GLOB_H
837int sh_files_has_metachar (const char * str)
838{
839 SL_ENTER(_("sh_files_has_metachar"));
840 if (NULL != strchr(str, '*'))
841 SL_RETURN(1, _("sh_files_has_metachar"));
842 else if (NULL != strchr(str, '?'))
843 SL_RETURN(1, _("sh_files_has_metachar"));
844 else if (NULL != (strchr(str, '[')))
845 SL_RETURN(1, _("sh_files_has_metachar"));
846 else
847 SL_RETURN(0, _("sh_files_has_metachar"));
848}
849
850
851int sh_files_globerr (const char * epath, int errnum)
852{
853 char * p;
854 char errbuf[SH_ERRBUF_SIZE];
855
856 SL_ENTER(_("sh_files_globerr"));
857
858 if (errnum == ENOTDIR || errnum == ENOENT)
859 {
860 SL_RETURN(0, _("sh_files_globerr"));
861 }
862
863 p = sh_util_safe_name (epath);
864 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_FI_GLOB,
865 sh_error_message (errnum, errbuf, sizeof(errbuf)), p);
866 SH_FREE(p);
867
868 SL_RETURN(0, _("sh_files_globerr"));
869}
870
871/* #ifdef HAVE_GLOB_H
872 */
873#endif
874
875int sh_files_push_file_int (int class, const char * str_s, size_t len)
876{
877 dirstack_t * new_item_ptr;
878 char * fileName;
879 int ret;
880
881 SL_ENTER(_("sh_files_push_file_int"));
882
883 fileName = SH_ALLOC(len+1);
884 sl_strlcpy(fileName, str_s, len+1);
885
886 new_item_ptr = (dirstack_t *) SH_ALLOC (sizeof(dirstack_t));
887
888 new_item_ptr->name = fileName;
889 new_item_ptr->class = class;
890 new_item_ptr->check_mask = sh_files_maskof(class);
891 new_item_ptr->rdepth = 0;
892 new_item_ptr->checked = S_FALSE;
893 new_item_ptr->is_reported = 0;
894 new_item_ptr->childs_checked = S_FALSE;
895
896 if (zfileList == NULL)
897 {
898 zfileList = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
899 if (zfileList == NULL)
900 {
901 (void) safe_logger (0, 0, NULL);
902 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
903 }
904 }
905
906 ret = zAVLInsert (zfileList, new_item_ptr);
907
908 if (-1 == ret)
909 {
910 (void) safe_logger (0, 0, NULL);
911 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
912 }
913
914 if (3 == ret)
915 {
916 if (sh.flag.started != S_TRUE)
917 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
918 fileName);
919 SH_FREE(fileName);
920 SH_FREE(new_item_ptr);
921 new_item_ptr = NULL;
922 }
923
924 if (new_item_ptr && MODI_AUDIT_ENABLED(new_item_ptr->check_mask))
925 {
926 sh_audit_mark(new_item_ptr->name);
927 }
928 SL_RETURN(0, _("sh_files_push_file_int"));
929}
930
931int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth);
932
933#ifdef HAVE_GLOB_H
934
935typedef struct globstack_entry {
936 char * name;
937 int class;
938 unsigned long check_mask;
939 int rdepth;
940 short type;
941 /* struct dirstack_entry * next; */
942} sh_globstack_t;
943
944static zAVLTree * zglobList = NULL;
945
946static void sh_files_pushglob (int class, int type, const char * p, int rdepth,
947 unsigned long check_mask, int flag)
948{
949 int globstatus = -1;
950 unsigned int gloop;
951 glob_t pglob;
952
953 SL_ENTER(_("sh_files_pushglob"));
954
955 pglob.gl_offs = 0;
956 globstatus = glob (p, 0, sh_files_globerr, &pglob);
957
958 if (globstatus == 0 && pglob.gl_pathc > 0)
959 {
960
961 if (sh.flag.checkSum != SH_CHECK_INIT)
962 {
963 sh_globstack_t * new_item_ptr;
964 char * fileName;
965 int ret;
966
967 fileName = sh_util_strdup (p);
968
969 new_item_ptr = (sh_globstack_t *) SH_ALLOC (sizeof(sh_globstack_t));
970
971 new_item_ptr->name = fileName;
972 new_item_ptr->class = class;
973 new_item_ptr->check_mask = (flag == 0) ? sh_files_maskof(class) : check_mask;
974 new_item_ptr->rdepth = rdepth;
975 new_item_ptr->type = type;
976
977 if (zglobList == NULL)
978 {
979 zglobList = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
980 if (zglobList == NULL)
981 {
982 (void) safe_logger (0, 0, NULL);
983 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
984 }
985 }
986
987 ret = zAVLInsert (zglobList, new_item_ptr);
988
989 if (ret != 0) /* already in list */
990 {
991 SH_FREE(fileName);
992 SH_FREE(new_item_ptr);
993 }
994 }
995
996 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
997 {
998 if (type == SH_LIST_FILE)
999 {
1000 sh_files_push_file_int (class, pglob.gl_pathv[gloop],
1001 sl_strlen(pglob.gl_pathv[gloop]));
1002 }
1003 else
1004 {
1005 which_dirList = type;
1006
1007 sh_files_push_dir_int (class, pglob.gl_pathv[gloop],
1008 sl_strlen(pglob.gl_pathv[gloop]), rdepth);
1009 }
1010 }
1011 }
1012 else
1013 {
1014 char * tmp = sh_util_safe_name (p);
1015
1016 if (pglob.gl_pathc == 0
1017#ifdef GLOB_NOMATCH
1018 || globstatus == GLOB_NOMATCH
1019#endif
1020 )
1021 sh_error_handle ((sh.flag.started != S_TRUE) ? SH_ERR_ERR : SH_ERR_NOTICE,
1022 FIL__, __LINE__,
1023 globstatus, MSG_FI_GLOB,
1024 _("No matches found"), tmp);
1025#ifdef GLOB_NOSPACE
1026 else if (globstatus == GLOB_NOSPACE)
1027 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1028 globstatus, MSG_FI_GLOB,
1029 _("Out of memory"), tmp);
1030#endif
1031#ifdef GLOB_ABORTED
1032 else if (globstatus == GLOB_ABORTED)
1033 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1034 globstatus, MSG_FI_GLOB,
1035 _("Read error"), tmp);
1036#endif
1037 else
1038 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1039 globstatus, MSG_FI_GLOB,
1040 _("Unknown error"), tmp);
1041
1042 SH_FREE(tmp);
1043
1044 }
1045
1046 globfree(&pglob);
1047 SL_RET0(_("sh_files_pushglob"));
1048 return;
1049}
1050
1051void sh_files_check_globPatterns()
1052{
1053 sh_globstack_t * testPattern;
1054 zAVLCursor cursor;
1055
1056 SL_ENTER(_("sh_files_check_globPatterns"));
1057
1058 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList); testPattern;
1059 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
1060 {
1061 sh_files_pushglob(testPattern->class, testPattern->type,
1062 testPattern->name, testPattern->rdepth,
1063 testPattern->check_mask, 1);
1064 }
1065 SL_RET0(_("sh_files_check_globPatterns"));
1066}
1067
1068/* the destructor
1069 */
1070void free_globstack (void * inptr)
1071{
1072 sh_globstack_t * here;
1073
1074 SL_ENTER(_("free_globstack"));
1075 if (inptr == NULL)
1076 SL_RET0(_("free_globstack"));
1077 else
1078 here = (sh_globstack_t *) inptr;
1079
1080 if (here->name != NULL)
1081 SH_FREE(here->name);
1082 SH_FREE(here);
1083 SL_RET0(_("free_globstack"));
1084}
1085
1086int sh_files_delglobstack ()
1087{
1088 SL_ENTER(_("sh_files_delglobstack"));
1089
1090 zAVLFreeTree (zglobList, free_globstack);
1091 zglobList = NULL;
1092
1093 SL_RETURN(0, _("sh_files_delglobstack"));
1094}
1095
1096
1097#else
1098void sh_files_check_globPatterns()
1099{
1100 return;
1101}
1102int sh_files_delglobstack ()
1103{
1104 return 0;
1105}
1106#endif
1107
1108static int sh_files_pushfile (int class, const char * str_s)
1109{
1110 size_t len;
1111 char * tmp;
1112 char * p;
1113
1114 static int reject = 0;
1115
1116 SL_ENTER(_("sh_files_pushfile"));
1117
1118 if (reject == 1)
1119 SL_RETURN((-1),_("sh_files_pushfile"));
1120
1121 /* if we push a filename from the command line, make sure it
1122 * is the only one -- and will stay the only one
1123 */
1124 if (sh.flag.opts == 1)
1125 {
1126 sh_files_delfilestack ();
1127 sh_files_deldirstack ();
1128 sh_files_delglobstack ();
1129 reject = 1;
1130 }
1131
1132 if (str_s == NULL || str_s[0] == '\0')
1133 SL_RETURN((-1),_("sh_files_pushfile"));
1134
1135 len = sl_strlen(str_s);
1136
1137 if ( (str_s[0] == '"' && str_s[len-1] == '"' ) ||
1138 (str_s[0] == '\'' && str_s[len-1] == '\'') )
1139 {
1140 if (len < 3)
1141 SL_RETURN((-1),_("sh_files_pushfile"));
1142 --len;
1143 p = sh_util_strdup_l(&str_s[1], len);
1144 p[len-1] = '\0';
1145 --len;
1146 }
1147 else
1148 {
1149 p = sh_util_strdup_l(str_s, len);
1150 }
1151
1152 p = sh_files_C_dequote(p, &len);
1153 if (!p || len == 0)
1154 SL_RETURN((-1), _("sh_files_pushfile"));
1155
1156 if (len >= PATH_MAX)
1157 {
1158 /* Name too long
1159 */
1160 tmp = sh_util_safe_name (p);
1161 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1162 tmp);
1163 SH_FREE(tmp);
1164 SL_RETURN((-1),_("sh_files_pushfile"));
1165 }
1166 else if (p[0] != '/')
1167 {
1168 /* Not an absolute path
1169 */
1170 tmp = sh_util_safe_name (p);
1171 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1172 tmp);
1173 SH_FREE(tmp);
1174 SL_RETURN((-1),_("sh_files_pushfile"));
1175 }
1176 else
1177 {
1178 /* remove a terminating '/', take care of the
1179 * special case of the root directory.
1180 */
1181 if (p[len-1] == '/' && len > 1)
1182 {
1183 p[len-1] = '\0';
1184 --len;
1185 }
1186 }
1187
1188#ifdef HAVE_GLOB_H
1189 if (0 == sh_files_has_metachar(p))
1190 {
1191 sh_files_push_file_int (class, p, len);
1192 }
1193 else
1194 {
1195 sh_files_pushglob (class, SH_LIST_FILE, p, 0, 0, 0);
1196 }
1197
1198#else
1199 sh_files_push_file_int (class, p, len);
1200#endif
1201
1202 SH_FREE(p);
1203 SL_RETURN((0),_("sh_files_pushfile"));
1204}
1205
1206
1207/* ------ directories ----- */
1208
1209int sh_files_is_allignore_int (char * str, zAVLTree * tree)
1210{
1211 dirstack_t * ptr;
1212
1213 SL_ENTER(_("sh_files_is_allignore"));
1214
1215 if (tree)
1216 {
1217 ptr = zAVLSearch(tree, str);
1218 if (ptr)
1219 {
1220 if (ptr->class == SH_LEVEL_ALLIGNORE)
1221 SL_RETURN( 1, _("sh_files_is_allignore"));
1222 else
1223 SL_RETURN( 0, _("sh_files_is_allignore"));
1224 }
1225 }
1226 SL_RETURN( 0, _("sh_files_is_allignore"));
1227}
1228
1229int sh_files_is_allignore (char * str)
1230{
1231 if (1 == sh_files_is_allignore_int(str, zdirListOne))
1232 return 1;
1233 if (NULL == zdirListTwo)
1234 return 0;
1235 return sh_files_is_allignore_int(str, zdirListTwo);
1236}
1237
1238unsigned long sh_dirs_chk (int which)
1239{
1240 zAVLTree * tree;
1241 zAVLCursor cursor;
1242 dirstack_t * ptr;
1243 dirstack_t * dst_ptr;
1244 int status;
1245 unsigned long dcount = 0;
1246 char * tmp;
1247
1248 SL_ENTER(_("sh_dirs_chk"));
1249
1250 if (which == 1)
1251 tree = zdirListOne;
1252 else
1253 tree = zdirListTwo;
1254
1255 for (ptr = (dirstack_t *) zAVLFirst(&cursor, tree); ptr;
1256 ptr = (dirstack_t *) zAVLNext(&cursor))
1257 {
1258 if (sig_urgent > 0) {
1259 SL_RETURN(dcount, _("sh_dirs_chk"));
1260 }
1261
1262 if (ptr->checked == S_FALSE)
1263 {
1264 /* 28 Aug 2001 check the top level directory
1265 */
1266 status = S_FALSE;
1267 dst_ptr = zAVLSearch(zfileList, ptr->name);
1268 if (dst_ptr)
1269 {
1270 if (dst_ptr->checked == S_FALSE)
1271 {
1272 BREAKEXIT(sh_files_filecheck);
1273 sh_files_filecheck (dst_ptr->class, dst_ptr->check_mask, ptr->name,
1274 NULL, &status, 0);
1275 dst_ptr->checked = S_TRUE;
1276 status = S_TRUE;
1277 }
1278 else
1279 {
1280 status = S_TRUE;
1281 }
1282 }
1283
1284 if (status == S_FALSE)
1285 sh_files_filecheck (ptr->class, ptr->check_mask, ptr->name, NULL, &status, 0);
1286
1287 BREAKEXIT(sh_files_checkdir);
1288 status = sh_files_checkdir (ptr->class, ptr->check_mask, ptr->rdepth, ptr->name,
1289 ptr->name);
1290
1291 if (status < 0 && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
1292 {
1293 /* directory is missing
1294 */
1295 if (S_FALSE == sh_ignore_chk_del(ptr->name))
1296 {
1297 if (0 != hashreport_missing(ptr->name,
1298 (ptr->class == SH_LEVEL_ALLIGNORE) ?
1299 ShDFLevel[ptr->class] :
1300 ShDFLevel[SH_ERR_T_DIR])) {
1301 tmp = sh_util_safe_name (ptr->name);
1302 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1303 ShDFLevel[ptr->class] :
1304 ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__,
1305 0, MSG_FI_MISS, tmp);
1306 SH_FREE(tmp);
1307 }
1308 }
1309 if (sh.flag.reportonce == S_TRUE)
1310 SET_SH_FFLAG_REPORTED(ptr->is_reported);
1311 }
1312 else
1313 {
1314 /* exists (status >= 0), but was missing (reported == TRUE)
1315 */
1316 if (status >= 0 && SH_FFLAG_REPORTED_SET(ptr->is_reported))
1317 {
1318 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
1319#if 0
1320 /* obsoleted (really?) by the mandatory sh_files_filecheck()
1321 * above, which will catch missing directories anyway
1322 */
1323 tmp = sh_util_safe_name (ptr->name);
1324 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1325 ShDFLevel[ptr->class] :
1326 ShDFLevel[SH_ERR_T_DIR],
1327 FIL__, __LINE__, 0, MSG_FI_ADD,
1328 tmp);
1329 SH_FREE(tmp);
1330#endif
1331 }
1332 else if (status == SH_FILE_UNKNOWN)
1333 {
1334 /* catchall
1335 */
1336 tmp = sh_util_safe_name (ptr->name);
1337 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
1338 MSG_FI_FAIL,
1339 tmp);
1340 SH_FREE(tmp);
1341 if (sh.flag.checkSum != SH_CHECK_INIT)
1342 sh_hash_set_visited_true(ptr->name);
1343 }
1344
1345 ++dcount;
1346 }
1347 ptr->checked = S_TRUE;
1348 ptr->childs_checked = S_TRUE;
1349 }
1350
1351 if (sig_urgent > 0) {
1352 SL_RETURN(dcount, _("sh_dirs_chk"));
1353 }
1354
1355 }
1356 SL_RETURN(dcount, _("sh_dirs_chk"));
1357}
1358
1359int sh_files_pushdir_prelink (const char * str_s)
1360{
1361 return (sh_files_pushdir (SH_LEVEL_PRELINK, str_s));
1362}
1363
1364int sh_files_pushdir_user0 (const char * str_s)
1365{
1366 return (sh_files_pushdir (SH_LEVEL_USER0, str_s));
1367}
1368
1369int sh_files_pushdir_user1 (const char * str_s)
1370{
1371 return (sh_files_pushdir (SH_LEVEL_USER1, str_s));
1372}
1373
1374int sh_files_pushdir_user2 (const char * str_s)
1375{
1376 return (sh_files_pushdir (SH_LEVEL_USER2, str_s));
1377}
1378
1379int sh_files_pushdir_user3 (const char * str_s)
1380{
1381 return (sh_files_pushdir (SH_LEVEL_USER3, str_s));
1382}
1383
1384int sh_files_pushdir_user4 (const char * str_s)
1385{
1386 return (sh_files_pushdir (SH_LEVEL_USER4, str_s));
1387}
1388
1389int sh_files_pushdir_attr (const char * str_s)
1390{
1391 return (sh_files_pushdir (SH_LEVEL_ATTRIBUTES, str_s));
1392}
1393
1394int sh_files_pushdir_ro (const char * str_s)
1395{
1396 return (sh_files_pushdir (SH_LEVEL_READONLY, str_s));
1397}
1398
1399int sh_files_pushdir_log (const char * str_s)
1400{
1401 return (sh_files_pushdir (SH_LEVEL_LOGFILES, str_s));
1402}
1403
1404int sh_files_pushdir_glog (const char * str_s)
1405{
1406 return (sh_files_pushdir (SH_LEVEL_LOGGROW, str_s));
1407}
1408
1409int sh_files_pushdir_noig (const char * str_s)
1410{
1411 return (sh_files_pushdir (SH_LEVEL_NOIGNORE, str_s));
1412}
1413
1414int sh_files_pushdir_allig (const char * str_s)
1415{
1416 return (sh_files_pushdir (SH_LEVEL_ALLIGNORE, str_s));
1417}
1418
1419int set_dirList (int which)
1420{
1421 if (which == 2)
1422 which_dirList = SH_LIST_DIR2;
1423 else
1424 which_dirList = SH_LIST_DIR1;
1425 return 0;
1426}
1427
1428int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth)
1429{
1430 zAVLTree * tree;
1431 dirstack_t * new_item_ptr;
1432 char * dirName;
1433 int ret;
1434
1435 SL_ENTER(_("sh_files_push_dir_int"));
1436
1437 dirName = SH_ALLOC(len+1);
1438 sl_strlcpy(dirName, tail, len+1);
1439
1440 new_item_ptr = (dirstack_t * ) SH_ALLOC (sizeof(dirstack_t));
1441
1442 new_item_ptr->name = dirName;
1443 new_item_ptr->class = class;
1444 new_item_ptr->check_mask = sh_files_maskof(class);
1445 new_item_ptr->rdepth = rdepth;
1446 new_item_ptr->checked = S_FALSE;
1447 new_item_ptr->is_reported = 0;
1448 new_item_ptr->childs_checked = S_FALSE;
1449
1450 if (which_dirList == SH_LIST_DIR1)
1451 {
1452 tree = zdirListOne;
1453 }
1454 else
1455 {
1456 tree = zdirListTwo;
1457 }
1458
1459 if (tree == NULL)
1460 {
1461 tree = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
1462 if (tree == NULL)
1463 {
1464 (void) safe_logger (0, 0, NULL);
1465 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1466 }
1467 if (which_dirList == SH_LIST_DIR1)
1468 zdirListOne = tree;
1469 else
1470 zdirListTwo = tree;
1471 }
1472
1473 ret = zAVLInsert (tree, new_item_ptr);
1474
1475 if (-1 == ret)
1476 {
1477 (void) safe_logger (0, 0, NULL);
1478 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1479 }
1480 if (3 == ret)
1481 {
1482 if (sh.flag.started != S_TRUE)
1483 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
1484 dirName);
1485 SH_FREE(dirName);
1486 SH_FREE(new_item_ptr);
1487 new_item_ptr = NULL;
1488 }
1489
1490 if (new_item_ptr && MODI_AUDIT_ENABLED(new_item_ptr->check_mask))
1491 {
1492 sh_audit_mark(new_item_ptr->name);
1493 }
1494
1495 SL_RETURN(0, _("sh_files_push_dir_int"));
1496}
1497
1498static int sh_files_pushdir (int class, const char * str_s)
1499{
1500 char * tmp;
1501 size_t len;
1502 int rdepth = 0;
1503 char * tail = NULL;
1504 char * p;
1505
1506 SL_ENTER(_("sh_files_pushdir"));
1507
1508 if (sh.flag.opts == 1) {
1509 sh_files_delfilestack ();
1510 sh_files_deldirstack ();
1511 sh_files_delglobstack ();
1512 }
1513
1514 if (str_s == NULL || str_s[0] == '\0')
1515 SL_RETURN((-1),_("sh_files_pushdir"));
1516
1517 len = sl_strlen(str_s);
1518
1519 if ( (str_s[0] == '"' && str_s[len-1] == '"' ) ||
1520 (str_s[0] == '\'' && str_s[len-1] == '\'') )
1521 {
1522 if (len < 3)
1523 SL_RETURN((-1),_("sh_files_pushdir"));
1524 --len;
1525 p = sh_util_strdup_l(&str_s[1], len);
1526 p[len-1] = '\0';
1527 --len;
1528 }
1529 else
1530 {
1531 p = sh_util_strdup_l(str_s, len);
1532 }
1533
1534 p = sh_files_C_dequote(p, &len);
1535 if (!p || len == 0)
1536 SL_RETURN((-1), _("sh_files_pushdir"));
1537
1538 if (p[0] != '/')
1539 {
1540 rdepth = strtol(p, &tail, 10);
1541 if (tail == p)
1542 {
1543 SH_FREE(p);
1544 SL_RETURN((-1), _("sh_files_pushdir"));
1545 }
1546 }
1547 else
1548 tail = p;
1549
1550
1551 if (tail == p)
1552 {
1553 /* Setting to an invalid number will force MaxRecursionLevel,
1554 * see sh_files_setrec_int()
1555 */
1556 rdepth = (-2);
1557 }
1558 else if ( (rdepth < (-1) || rdepth > 99) ||
1559 ((rdepth == (-1)) && (class != SH_LEVEL_ALLIGNORE)) )
1560 {
1561 SH_FREE(p);
1562 SL_RETURN((-1), _("sh_files_pushdir"));
1563 }
1564
1565 len = sl_strlen(tail);
1566
1567 if (len >= PATH_MAX)
1568 {
1569 tmp = sh_util_safe_name (tail);
1570 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1571 tmp);
1572 SH_FREE(tmp);
1573 SH_FREE(p);
1574 SL_RETURN((-1), _("sh_files_pushdir"));
1575 }
1576 else if (len < 1)
1577 {
1578 SH_FREE(p);
1579 SL_RETURN((-1), _("sh_files_pushdir"));
1580 }
1581 else if (tail[0] != '/')
1582 {
1583 tmp = sh_util_safe_name (tail);
1584 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1585 tmp);
1586 SH_FREE(tmp);
1587 SH_FREE(p);
1588 SL_RETURN((-1), _("sh_files_pushdir"));
1589 }
1590 else
1591 {
1592 if (tail[len-1] == '/' && len > 1)
1593 {
1594 tail[len-1] = '\0';
1595 --len;
1596 }
1597 }
1598
1599#ifdef HAVE_GLOB_H
1600 if (0 == sh_files_has_metachar(tail))
1601 {
1602 sh_files_push_dir_int (class, tail, len, rdepth);
1603 }
1604 else
1605 {
1606 sh_files_pushglob (class, which_dirList, tail, rdepth, 0, 0);
1607 }
1608#else
1609 sh_files_push_dir_int (class, tail, len, rdepth);
1610#endif
1611
1612 SH_FREE(p);
1613 SL_RETURN((0), _("sh_files_pushdir"));
1614}
1615
1616/**
1617struct sh_dirent {
1618 char * sh_d_name;
1619 struct sh_dirent * next;
1620};
1621**/
1622
1623void kill_sh_dirlist (struct sh_dirent * dirlist)
1624{
1625 struct sh_dirent * this;
1626
1627 while (dirlist)
1628 {
1629 this = dirlist->next;
1630 SH_FREE(dirlist->sh_d_name);
1631 SH_FREE(dirlist);
1632 dirlist = this;
1633 }
1634 return;
1635}
1636
1637/* -- add an entry to a directory listing
1638 */
1639struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry,
1640 struct sh_dirent * dirlist)
1641{
1642 struct sh_dirent * this;
1643 size_t len;
1644
1645 if (thisEntry == NULL)
1646 return dirlist;
1647
1648 len = sl_strlen(thisEntry->d_name);
1649 if (len == 0)
1650 return dirlist;
1651 ++len;
1652
1653 this = SH_ALLOC(sizeof(struct sh_dirent));
1654 if (!this)
1655 return dirlist;
1656
1657 this->sh_d_name = SH_ALLOC(len);
1658 sl_strlcpy(this->sh_d_name, thisEntry->d_name, len);
1659
1660 this->next = dirlist;
1661 return this;
1662}
1663
1664static int sh_check_hardlinks = S_TRUE;
1665
1666/* Simply sets our boolean as to whether this check is active
1667 */
1668int sh_files_check_hardlinks (const char * opt)
1669{
1670 int i;
1671 SL_ENTER(_("sh_files_check_hardlinks"));
1672 i = sh_util_flagval(opt, &sh_check_hardlinks);
1673 SL_RETURN(i, _("sh_files_check_hardlinks"));
1674}
1675
1676struct sh_hle_struct {
1677 long offset;
1678 char * path;
1679 struct sh_hle_struct * next;
1680};
1681
1682static struct sh_hle_struct * sh_hl_exc = NULL;
1683
1684int sh_files_hle_reg (const char * str)
1685{
1686 long offset;
1687 size_t len;
1688 char * path;
1689
1690 struct sh_hle_struct * tmp = sh_hl_exc;
1691
1692 SL_ENTER(_("sh_files_hle_reg"));
1693
1694 /* Free the linked list if called with NULL argument
1695 */
1696 if (str == NULL)
1697 {
1698 while (tmp)
1699 {
1700 sh_hl_exc = tmp->next;
1701 SH_FREE(tmp->path);
1702 SH_FREE(tmp);
1703 tmp = sh_hl_exc;
1704 }
1705 sh_hl_exc = NULL;
1706 SL_RETURN(0, _("sh_files_hle_reg"));
1707 }
1708
1709 /* We expect 'offset:/path'
1710 */
1711 offset = strtol(str, &path, 0);
1712 if ((path == NULL) || (*path == '\0') || (*path != ':') || (path[1] != '/'))
1713 {
1714 SL_RETURN(-1, _("sh_files_hle_reg"));
1715 }
1716 ++path;
1717 len = 1 + sl_strlen(path);
1718
1719 tmp = SH_ALLOC(sizeof(struct sh_hle_struct));
1720 tmp->path = SH_ALLOC(len);
1721 sl_strlcpy (tmp->path, path, len);
1722 tmp->offset = offset;
1723 tmp->next = sh_hl_exc;
1724 sh_hl_exc = tmp;
1725
1726 SL_RETURN(0, _("sh_files_hle_reg"));
1727}
1728
1729#if !defined(HOST_IS_DARWIN)
1730static int sh_files_hle_test (int offset, char * path)
1731{
1732 struct sh_hle_struct * tmp = sh_hl_exc;
1733
1734 SL_ENTER(_("sh_files_hle_reg"));
1735
1736 while(tmp)
1737 {
1738 if ((offset == tmp->offset) && (0 == strcmp(path, tmp->path)))
1739 {
1740 SL_RETURN(0, _("sh_files_hle_test"));
1741 }
1742 tmp = tmp->next;
1743 }
1744 SL_RETURN(-1, _("sh_files_hle_test"));
1745}
1746#endif
1747
1748/* -- check a single directory and its content
1749 */
1750static int sh_files_checkdir (int iclass, unsigned long check_mask,
1751 int idepth, char * iname,
1752 char * relativeName)
1753{
1754 struct sh_dirent * dirlist;
1755 struct sh_dirent * dirlist_orig;
1756
1757 DIR * thisDir = NULL;
1758 struct dirent * thisEntry;
1759 int status;
1760 int dummy = S_FALSE;
1761 dir_type * theDir;
1762 ShFileType checkit;
1763 static unsigned int state = 1;
1764
1765 file_type * theFile;
1766 char * tmpname;
1767 char * tmpcat;
1768 char errbuf[SH_ERRBUF_SIZE];
1769
1770 int rdepth = 0;
1771 int class = 0;
1772 int rdepth_next;
1773 int class_next;
1774 int file_class_next;
1775 unsigned long check_mask_next;
1776 unsigned long file_check_mask_next;
1777
1778 int checked_flag = S_FALSE;
1779 int cchecked_flag = S_FALSE;
1780
1781 dirstack_t * dst_ptr;
1782 dirstack_t * tmp_ptr;
1783
1784 int hardlink_num = 0;
1785#if !defined(HOST_IS_DARWIN)
1786 size_t len;
1787#endif
1788
1789 SL_ENTER(_("sh_files_checkdir"));
1790
1791 if (sig_urgent > 0) {
1792 SL_RETURN((0), _("sh_files_checkdir"));
1793 }
1794
1795 if (iname == NULL || idepth < (-1))
1796 SL_RETURN((-1), _("sh_files_checkdir"));
1797
1798 if (idepth < 0)
1799 {
1800 /* hash_remove_tree (iname); */
1801 SL_RETURN((0), _("sh_files_checkdir"));
1802 }
1803
1804 rdepth = idepth;
1805 class = iclass;
1806
1807 tmpname = sh_util_safe_name (iname);
1808
1809 /* ---- check for obscure name ----
1810 */
1811 if (iclass != SH_LEVEL_ALLIGNORE)
1812 {
1813 sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], iname, S_TRUE);
1814 }
1815
1816 if (flag_err_info == SL_TRUE)
1817 {
1818 char pstr[32];
1819
1820 sl_strlcpy(pstr, sh_hash_getpolicy(iclass), sizeof(pstr));
1821 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, pstr, tmpname);
1822 }
1823
1824 /* ---- check input ----
1825 */
1826 if ( sl_strlen(iname) >= PATH_MAX)
1827 {
1828 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1829 MSG_FI_2LONG,
1830 tmpname);
1831 SH_FREE(tmpname);
1832 SL_RETURN((-1), _("sh_files_checkdir"));
1833 }
1834
1835 /* ---- check for absolute path ---- */
1836 if ( iname[0] != '/')
1837 {
1838 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1839 MSG_FI_NOPATH,
1840 tmpname);
1841 SH_FREE(tmpname);
1842 SL_RETURN((-1), _("sh_files_checkdir"));
1843 }
1844
1845 /* ---- stat the directory ----
1846 */
1847 theFile = SH_ALLOC(sizeof(file_type));
1848 sl_strlcpy (theFile->fullpath, iname, PATH_MAX);
1849 theFile->attr_string = NULL;
1850 theFile->link_path = NULL;
1851 theFile->check_mask = check_mask;
1852
1853 (void) relativeName;
1854 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_DIR],
1855 iname,
1856 theFile, NULL, iclass);
1857
1858 if ((sig_termfast == 1) || (sig_terminate == 1))
1859 {
1860 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1861 if (theFile->link_path) SH_FREE(theFile->link_path);
1862 SH_FREE(theFile);
1863 SL_RETURN((0), _("sh_files_checkdir"));
1864 }
1865
1866 if (status == -1)
1867 {
1868 SH_FREE(tmpname);
1869 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1870 if (theFile->link_path) SH_FREE(theFile->link_path);
1871 SH_FREE(theFile);
1872 SL_RETURN((-1), _("sh_files_checkdir"));
1873 }
1874
1875 if (theFile->c_mode[0] != 'd')
1876 {
1877 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1878 MSG_FI_NODIR,
1879 tmpname);
1880 SH_FREE(tmpname);
1881 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1882 if (theFile->link_path) SH_FREE(theFile->link_path);
1883 SH_FREE(theFile);
1884 SL_RETURN((-1), _("sh_files_checkdir"));
1885 }
1886
1887 hardlink_num = theFile->hardlinks;
1888
1889 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1890 if (theFile->link_path) SH_FREE(theFile->link_path);
1891 SH_FREE(theFile);
1892
1893 /* ---- open directory for reading ----
1894 *
1895 * opendir() will fail with ENOTDIR if the path has been changed
1896 * to a non-directory in between lstat() and opendir().
1897 */
1898 thisDir = opendir (iname);
1899
1900 if (thisDir == NULL)
1901 {
1902 status = errno;
1903 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1904 MSG_E_OPENDIR,
1905 sh_error_message (status, errbuf, sizeof(errbuf)), tmpname);
1906 SH_FREE(tmpname);
1907 SL_RETURN((-1), _("sh_files_checkdir"));
1908 }
1909
1910 theDir = SH_ALLOC(sizeof(dir_type));
1911
1912 theDir->NumRegular = 0;
1913 theDir->NumDirs = 0;
1914 theDir->NumSymlinks = 0;
1915 theDir->NumFifos = 0;
1916 theDir->NumSockets = 0;
1917 theDir->NumCDev = 0;
1918 theDir->NumBDev = 0;
1919 theDir->NumDoor = 0;
1920 theDir->NumPort = 0;
1921 theDir->NumAll = 0;
1922 theDir->TotalBytes = 0;
1923 sl_strlcpy (theDir->DirPath, iname, PATH_MAX);
1924
1925
1926 /* ---- read ----
1927 */
1928 SH_MUTEX_LOCK(mutex_readdir);
1929
1930 dirlist = NULL;
1931 dirlist_orig = NULL;
1932
1933 do {
1934 thisEntry = readdir (thisDir);
1935 if (thisEntry != NULL)
1936 {
1937 ++theDir->NumAll;
1938 if (sl_strcmp (thisEntry->d_name, ".") == 0)
1939 {
1940 ++theDir->NumDirs;
1941 continue;
1942 }
1943 if (sl_strcmp (thisEntry->d_name, "..") == 0)
1944 {
1945 ++theDir->NumDirs;
1946 continue;
1947 }
1948 dirlist = addto_sh_dirlist (thisEntry, dirlist);
1949 }
1950 } while (thisEntry != NULL);
1951
1952 SH_MUTEX_UNLOCK(mutex_readdir);
1953
1954 closedir (thisDir);
1955
1956 ++sh.statistics.dirs_checked;
1957
1958 dirlist_orig = dirlist;
1959
1960 do {
1961
1962 /* If the directory is empty, dirlist = NULL
1963 */
1964 if (!dirlist)
1965 break;
1966
1967 if (sig_termfast == 1)
1968 {
1969 SH_FREE(theDir);
1970 SL_RETURN((0), _("sh_files_checkdir"));
1971 }
1972
1973 BREAKEXIT(sh_derr);
1974
1975#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
1976 if (0 == (rand_r(&state) % 5)) (void) sh_derr();
1977#else
1978 if (0 == state * (rand() % 5)) (void) sh_derr();
1979#endif
1980
1981 /* ---- Check the file. ----
1982 */
1983 tmpcat = SH_ALLOC(PATH_MAX);
1984 sl_strlcpy(tmpcat, iname, PATH_MAX);
1985 if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/')
1986 sl_strlcat(tmpcat, "/", PATH_MAX);
1987 sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX);
1988
1989 rdepth_next = rdepth - 1;
1990 class_next = class;
1991 check_mask_next = check_mask;
1992 file_class_next = class;
1993 file_check_mask_next = check_mask;
1994 checked_flag = -1;
1995 cchecked_flag = -1;
1996
1997 /* Wed Aug 24 2005 compare against dirListOne, dirListTwo
1998 * this fixes the problem that the directory special file
1999 * is checked with the policy of the parent directory
2000 */
2001 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2002
2003 if (dst_ptr)
2004 {
2005 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2006 * this fixes the problem that a policy for the directory
2007 * inode erroneously becomes a policy for the directory itself.
2008 */
2009 file_class_next = dst_ptr->class;
2010 file_check_mask_next = dst_ptr->check_mask;
2011 checked_flag = dst_ptr->checked;
2012 cchecked_flag = dst_ptr->childs_checked;
2013 }
2014
2015 if (checked_flag == -1)
2016 {
2017 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2018
2019 if (dst_ptr)
2020 {
2021 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2022 * this fixes the problem that a policy for the directory
2023 * inode erroneously becomes a policy for the directory itself.
2024 */
2025 file_class_next = dst_ptr->class;
2026 file_check_mask_next = dst_ptr->check_mask;
2027 checked_flag = dst_ptr->checked;
2028 cchecked_flag = dst_ptr->childs_checked;
2029 }
2030 }
2031
2032 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2033
2034 if (dst_ptr)
2035 {
2036 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2037 * this fixes the problem that a policy for the directory
2038 * inode erroneously becomes a policy for the directory itself.
2039 */
2040 file_class_next = dst_ptr->class;
2041 file_check_mask_next = dst_ptr->check_mask;
2042 checked_flag = dst_ptr->checked;
2043 /* not set, hence always FALSE */
2044 /* cchecked_flag = dst_ptr->childs_checked; */
2045 }
2046
2047 /* ---- Has been checked already. ----
2048 */
2049 if (checked_flag == S_TRUE && cchecked_flag == S_TRUE)
2050 {
2051 /* Mar 11 2004 get ftype for complete directory count
2052 */
2053 checkit = sh_unix_get_ftype(tmpcat);
2054 if (checkit == SH_FILE_DIRECTORY)
2055 {
2056 ++theDir->NumDirs;
2057 }
2058 SH_FREE(tmpcat);
2059 dirlist = dirlist->next;
2060 continue;
2061 }
2062
2063 /* --- May be true, false, or not found. ---
2064 */
2065 if (checked_flag == S_TRUE)
2066 {
2067 /* -- need only the file type --
2068 */
2069 checkit = sh_unix_get_ftype(tmpcat);
2070 }
2071 else
2072 {
2073 /* -- need to check the file itself --
2074 */
2075 if (dst_ptr && sh.flag.reportonce == S_TRUE)
2076 dummy = dst_ptr->is_reported;
2077
2078 checkit = sh_files_filecheck (file_class_next, file_check_mask_next,
2079 iname,
2080 dirlist->sh_d_name,
2081 &dummy, 0);
2082
2083 if (dst_ptr && checked_flag == S_FALSE)
2084 dst_ptr->checked = S_TRUE;
2085 /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag
2086 */
2087 if (dst_ptr && sh.flag.reportonce == S_TRUE)
2088 dst_ptr->is_reported = dummy;
2089 }
2090
2091 if (checkit == SH_FILE_REGULAR)
2092 ++theDir->NumRegular;
2093
2094 else if (checkit == SH_FILE_DIRECTORY)
2095 {
2096 ++theDir->NumDirs;
2097
2098 if (rdepth_next >= 0 && cchecked_flag != S_TRUE)
2099 {
2100 rdepth_next = rdepth - 1;
2101
2102 /* check whether the new directory is in the
2103 * list with a recursion depth already defined
2104 */
2105 checked_flag = -1;
2106 cchecked_flag = -1;
2107
2108 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2109
2110 if (tmp_ptr)
2111 {
2112 TPT((0, FIL__, __LINE__,
2113 _("msg=<%s -> recursion depth %d\n>"),
2114 tmp_ptr->name, tmp_ptr->rdepth));
2115 rdepth_next = tmp_ptr->rdepth;
2116 class_next = tmp_ptr->class;
2117 check_mask_next = tmp_ptr->check_mask;
2118 /* 28. Aug 2001 reversed
2119 */
2120 cchecked_flag = tmp_ptr->childs_checked;
2121 checked_flag = tmp_ptr->checked;
2122 }
2123
2124 if (checked_flag == -1)
2125 {
2126 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2127
2128 if (tmp_ptr)
2129 {
2130 TPT((0, FIL__, __LINE__,
2131 _("msg=<%s -> recursion depth %d\n>"),
2132 tmp_ptr->name, tmp_ptr->rdepth));
2133 rdepth_next = tmp_ptr->rdepth;
2134 class_next = tmp_ptr->class;
2135 check_mask_next = tmp_ptr->check_mask;
2136 /* 28. Aug 2001 reversed
2137 */
2138 cchecked_flag = tmp_ptr->childs_checked;
2139 checked_flag = tmp_ptr->checked;
2140 }
2141 }
2142
2143 if (cchecked_flag == S_FALSE)
2144 {
2145 sh_files_checkdir (class_next, check_mask_next, rdepth_next, tmpcat,
2146 dirlist->sh_d_name);
2147 tmp_ptr->childs_checked = S_TRUE;
2148 /*
2149 * 04. Feb 2006 avoid double checking
2150 */
2151 tmp_ptr->checked = S_TRUE;
2152 }
2153 else if (checked_flag == -1)
2154 sh_files_checkdir (class_next, check_mask_next, rdepth_next, tmpcat,
2155 dirlist->sh_d_name);
2156
2157 }
2158 }
2159
2160 else if (checkit == SH_FILE_SYMLINK) ++theDir->NumSymlinks;
2161 else if (checkit == SH_FILE_FIFO) ++theDir->NumFifos;
2162 else if (checkit == SH_FILE_SOCKET) ++theDir->NumSockets;
2163 else if (checkit == SH_FILE_CDEV) ++theDir->NumCDev;
2164 else if (checkit == SH_FILE_BDEV) ++theDir->NumBDev;
2165 else if (checkit == SH_FILE_DOOR) ++theDir->NumDoor;
2166 else if (checkit == SH_FILE_PORT) ++theDir->NumPort;
2167
2168 SH_FREE(tmpcat);
2169
2170 if ((sig_termfast == 1) || (sig_terminate == 1))
2171 {
2172 SH_FREE(theDir);
2173 SL_RETURN((0), _("sh_files_checkdir"));
2174 }
2175
2176 dirlist = dirlist->next;
2177
2178 if (dst_ptr)
2179 dst_ptr->childs_checked = S_TRUE;
2180
2181 } while (dirlist != NULL);
2182
2183 if (flag_err_info == SL_TRUE)
2184 {
2185 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
2186 theDir->NumDirs,
2187 theDir->NumRegular,
2188 theDir->NumSymlinks,
2189 theDir->NumFifos,
2190 theDir->NumSockets,
2191 theDir->NumCDev,
2192 theDir->NumBDev);
2193 }
2194
2195 kill_sh_dirlist (dirlist_orig);
2196
2197#if !defined(HOST_IS_DARWIN)
2198 /*
2199 * Hardlink check; not done on MacOS X because of resource forks
2200 */
2201 if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir->NumDirs))
2202 {
2203 if (0 != sh_files_hle_test(hardlink_num-theDir->NumDirs, iname))
2204 {
2205 len = strlen(tmpname);
2206 if (sl_ok_adds(len, 256))
2207 len += 256;
2208 tmpcat = SH_ALLOC(len);
2209 sl_snprintf(tmpcat, len,
2210 _("%s: subdirectory count (%d) != hardlinks (%d)"),
2211 tmpname, theDir->NumDirs, hardlink_num);
2212 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2213 MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir"));
2214 SH_FREE(tmpcat);
2215 }
2216 }
2217#endif
2218
2219 SH_FREE(tmpname);
2220 SH_FREE(theDir);
2221
2222 SL_RETURN((0), _("sh_files_checkdir"));
2223}
2224
2225int get_the_fd (SL_TICKET ticket);
2226
2227static int sh_use_rsrc = S_FALSE;
2228
2229int sh_files_use_rsrc(const char * str)
2230{
2231 return sh_util_flagval(str, &sh_use_rsrc);
2232}
2233
2234static void * sh_dummy_fileName;
2235static void * sh_dummy_tmpname;
2236static void * sh_dummy_tmpdir;
2237
2238ShFileType sh_files_filecheck (int class, unsigned long check_mask,
2239 char * dirName,
2240 char * infileName,
2241 int * reported,
2242 int rsrcflag)
2243{
2244 /* 28 Aug 2001 allow NULL fileName
2245 */
2246 char * fullpath;
2247 char fileHash[2*(KEY_LEN + 1)];
2248 int status;
2249 file_type * theFile;
2250 char * tmpdir;
2251 char * tmpname;
2252 char * fileName;
2253 struct utimbuf utime_buf;
2254 static unsigned int state = 1;
2255 char sc;
2256
2257 SL_ENTER(_("sh_files_filecheck"));
2258
2259 fullpath = SH_ALLOC(PATH_MAX);
2260 theFile = SH_ALLOC(sizeof(file_type));
2261
2262 /* Take the address to keep gcc from putting it into a register.
2263 * Avoids the 'clobbered by longjmp' warning.
2264 */
2265 sh_dummy_fileName = (void *) &fileName;
2266 sh_dummy_tmpname = (void *) &tmpname;
2267 sh_dummy_tmpdir = (void *) &tmpdir;
2268
2269 BREAKEXIT(sh_derr);
2270
2271#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
2272 if (0 == (rand_r(&state) % 2)) (void) sh_derr();
2273#else
2274 if (0 == state * (rand() % 2)) (void) sh_derr();
2275#endif
2276
2277 if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0')
2278 && (infileName[0] == '/') && (infileName[1] == '\0'))
2279 {
2280 fileName = NULL;
2281 }
2282 else
2283 {
2284 fileName = infileName;
2285 }
2286
2287 /* fileName may be NULL if this is a directory
2288 */
2289 if (dirName == NULL /* || fileName == NULL */)
2290 {
2291 SH_MUTEX_LOCK(mutex_thread_nolog);
2292 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL);
2293 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2294 SH_FREE(fullpath);
2295 SH_FREE(theFile);
2296 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2297 }
2298
2299 if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) &&
2300 (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME],
2301 fileName, S_FALSE)))
2302 {
2303 if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0'))
2304 {
2305 tmpname = sh_util_safe_name (fileName);
2306 SH_MUTEX_LOCK(mutex_thread_nolog);
2307 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2308 MSG_FI_OBSC2,
2309 "", tmpname);
2310 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2311 SH_FREE(tmpname);
2312 }
2313 else
2314 {
2315 tmpdir = sh_util_safe_name (dirName);
2316 tmpname = sh_util_safe_name (fileName);
2317 SH_MUTEX_LOCK(mutex_thread_nolog);
2318 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2319 MSG_FI_OBSC2,
2320 tmpdir, tmpname);
2321 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2322 SH_FREE(tmpname);
2323 SH_FREE(tmpdir);
2324 }
2325 }
2326
2327 /* sh_files_fullpath accepts NULL fileName
2328 */
2329 if (0 != sh_files_fullpath (dirName, fileName, fullpath))
2330 {
2331 tmpdir = sh_util_safe_name (dirName);
2332 tmpname = sh_util_safe_name (fileName);
2333 SH_MUTEX_LOCK(mutex_thread_nolog);
2334 sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0,
2335 MSG_FI_2LONG2,
2336 tmpdir, tmpname);
2337 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2338 SH_FREE(tmpname);
2339 SH_FREE(tmpdir);
2340 SH_FREE(fullpath);
2341 SH_FREE(theFile);
2342 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2343 }
2344
2345
2346 /* stat the file and determine checksum (if a regular file)
2347 */
2348 sl_strlcpy (theFile->fullpath, fullpath, PATH_MAX);
2349 theFile->check_mask = check_mask /* sh_files_maskof(class) */;
2350 theFile->file_reported = (*reported);
2351 theFile->attr_string = NULL;
2352 theFile->link_path = NULL;
2353
2354 TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"), fullpath));
2355
2356 status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ?
2357 ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE],
2358 fileName,
2359 theFile, fileHash, class);
2360
2361 if (status != 0)
2362 {
2363 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
2364 fullpath, status));
2365 if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
2366 sh_hash_set_visited_true (fullpath);
2367 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2368 if (theFile->link_path) SH_FREE(theFile->link_path);
2369 SH_FREE(fullpath);
2370 SH_FREE(theFile);
2371 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2372 }
2373
2374 if (sig_termfast == 1) {
2375 goto ret_point;
2376 }
2377
2378 /* report
2379 */
2380 if ((flag_err_debug == SL_TRUE) && (theFile->c_mode[0] == '-'))
2381 {
2382 tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
2383 SH_MUTEX_LOCK(mutex_thread_nolog);
2384 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM,
2385 fileHash, tmpname);
2386 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2387 SH_FREE(tmpname);
2388 }
2389 ++sh.statistics.files_checked;
2390
2391 if ( sh.flag.checkSum == SH_CHECK_INIT /* && sh.flag.update == S_FALSE */)
2392 {
2393 sh_hash_pushdata (theFile, fileHash);
2394 }
2395 else if (sh.flag.checkSum == SH_CHECK_CHECK
2396 /* && theFile.c_mode[0] == '-' */
2397 /* && class != SH_LEVEL_ALLIGNORE */
2398 )
2399 {
2400 sh_hash_compdata (class, theFile, fileHash, NULL, -1);
2401 }
2402
2403 (*reported) = theFile->file_reported;
2404
2405 /* reset the access time
2406 */
2407 if (class == SH_LEVEL_NOIGNORE && (theFile->check_mask & MODI_ATM) != 0)
2408 {
2409 utime_buf.actime = (time_t) theFile->atime;
2410 utime_buf.modtime = (time_t) theFile->mtime;
2411#if !defined(O_NOATIME)
2412 retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf);
2413#endif
2414 }
2415
2416#if defined(HOST_IS_DARWIN)
2417 /*
2418 * Check for resource fork
2419 */
2420 if ( (sh_use_rsrc == S_TRUE) && (theFile->c_mode[0] != 'd') && (rsrcflag == 0) )
2421 {
2422 int dummy;
2423 static int rsrc_init = 0;
2424 static char rsrc[17];
2425 char * testpath = SH_ALLOC(PATH_MAX);
2426
2427 if (rsrc_init == 0) {
2428 sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17);
2429 rsrc_init = 1;
2430 }
2431 sl_strlcpy (testpath, fullpath, PATH_MAX);
2432 sl_strlcat (testpath, "/", PATH_MAX);
2433 sl_strlcat (testpath, rsrc, PATH_MAX);
2434
2435 if (sl_strlen(testpath) == (17 + sl_strlen(fullpath)))
2436 {
2437 if (S_TRUE == sh_unix_file_exists (testpath))
2438 {
2439 sh_files_filecheck (class, fullpath, rsrc, &dummy, 1);
2440 }
2441 }
2442 SH_FREE(testpath);
2443 }
2444#else
2445 (void) rsrcflag; /* avoid compiler warning */
2446#endif
2447
2448 ret_point:
2449
2450 sc = theFile->c_mode[0];
2451
2452 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2453 if (theFile->link_path) SH_FREE(theFile->link_path);
2454 SH_FREE(fullpath);
2455 SH_FREE(theFile);
2456
2457 switch (sc)
2458 {
2459 case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck"));
2460 case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck"));
2461 case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck"));
2462 case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck"));
2463 case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck"));
2464 case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck"));
2465 case 'D': SL_RETURN(SH_FILE_DOOR, _("sh_files_filecheck"));
2466 case 'P': SL_RETURN(SH_FILE_PORT, _("sh_files_filecheck"));
2467 case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck"));
2468 default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2469 }
2470
2471 /* notreached */
2472}
2473
2474/* concatenate statpath = testdir"/"d_name
2475 */
2476static int sh_files_fullpath (char * testdir, char * d_name, char * statpath)
2477{
2478 int llen = 0;
2479
2480 SL_ENTER(_("sh_files_fullpath"));
2481
2482 if (testdir != NULL)
2483 {
2484 if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) )
2485 SL_RETURN((-1),_("sh_files_fullpath"));
2486 sl_strlcpy(statpath, testdir, PATH_MAX - 1);
2487 }
2488 if (d_name != NULL)
2489 {
2490 if (llen > 1 || statpath[0] != '/')
2491 sl_strlcat(statpath, "/", PATH_MAX);
2492 if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX)
2493 SL_RETURN((-1),_("sh_files_fullpath"));
2494 sl_strlcat(statpath, d_name, PATH_MAX);
2495 }
2496 if (statpath == NULL)
2497 SL_RETURN((-1),_("sh_files_fullpath"));
2498 SL_RETURN((0),_("sh_files_fullpath"));
2499}
2500
2501/* -----------------------------------
2502 *
2503 * The following two routines serve to
2504 * verify that the user has selected
2505 * a proper setup for file policies.
2506 *
2507 * -----------------------------------
2508 */
2509static int check_file(char * name)
2510{
2511 dirstack_t * pfilL;
2512 zAVLCursor cursor;
2513
2514 SL_ENTER(_("check_file"));
2515
2516 if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name))
2517 SL_RETURN(0, _("check_file"));
2518
2519 for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL;
2520 pfilL = (dirstack_t *) zAVLNext (&cursor))
2521 {
2522 if (0 == strcmp(name, pfilL->name) &&
2523 (pfilL->check_mask & MODI_ATM) == 0 &&
2524 (pfilL->check_mask & MODI_CTM) == 0 &&
2525 (pfilL->check_mask & MODI_MTM) == 0)
2526 SL_RETURN(0, _("check_file"));
2527 }
2528 SL_RETURN((-1), _("check_file"));
2529}
2530
2531int sh_files_test_setup_int (zAVLTree * tree)
2532{
2533 int dlen, flen;
2534 zAVLCursor cursor1;
2535 zAVLCursor cursor2;
2536
2537 dirstack_t * pdirL;
2538 dirstack_t * pfilL;
2539
2540 SL_ENTER(_("sh_files_test_setup"));
2541
2542 for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL;
2543 pdirL = (dirstack_t *) zAVLNext (&cursor1))
2544 {
2545 dlen = strlen(pdirL->name);
2546
2547 for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL;
2548 pfilL = (dirstack_t *) zAVLNext (&cursor2))
2549 {
2550 flen = strlen(pfilL->name);
2551
2552 /* check whether file is in tree of dir
2553 */
2554 if ((pfilL->class == SH_LEVEL_READONLY) ||
2555 (pfilL->class == SH_LEVEL_NOIGNORE))
2556 {
2557 ; /* do nothing */
2558 }
2559 else
2560 {
2561 if ((flen > (dlen+1)) &&
2562 (pfilL->name[dlen] == '/') &&
2563 (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/
2564 (0 == strncmp(pfilL->name, pdirL->name, dlen)))
2565 {
2566 if ((pdirL->check_mask & MODI_ATM) != 0 ||
2567 (pdirL->check_mask & MODI_MTM) != 0 ||
2568 (pdirL->check_mask & MODI_CTM) != 0)
2569 {
2570 if (check_file (pdirL->name) != 0)
2571 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL,
2572 pdirL->name, pfilL->name);
2573 }
2574 }
2575 }
2576 }
2577 }
2578
2579 SL_RETURN((0), _("sh_files_test_setup"));
2580}
2581
2582int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList)
2583{
2584 int retval = 0;
2585 zAVLCursor cursor;
2586 dirstack_t * first;
2587
2588 for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first;
2589 first = (dirstack_t *) zAVLNext (&cursor))
2590 {
2591
2592 if (NULL != zAVLSearch(secondList, first->name))
2593 {
2594 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
2595 first->name);
2596 retval = 1;
2597 }
2598 }
2599 return retval;
2600}
2601
2602extern void aud_exit (const char * file, int line, int fd);
2603
2604int sh_files_test_setup ()
2605{
2606 int retval = 0;
2607
2608 /* Test for modifications allowed in ReadOnly directory
2609 */
2610 sh_files_test_setup_int (zdirListOne);
2611 sh_files_test_setup_int (zdirListTwo);
2612
2613 /* Test for files/dirz defined twice
2614 */
2615 retval = sh_files_test_double (zdirListOne, zdirListTwo);
2616 if (retval != 0)
2617 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2618
2619 retval = sh_files_test_double (zdirListTwo, zdirListOne);
2620 if (retval != 0)
2621 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2622
2623
2624 /*
2625 retval = sh_files_test_double (zfileList, NULL);
2626 if (retval != 0)
2627 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2628 */
2629 return 0;
2630}
2631
2632#endif
2633
2634#ifdef SH_CUTEST
2635#include "CuTest.h"
2636
2637void Test_file_dequote (CuTest *tc)
2638{
2639#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
2640
2641 char str1[] = "1234567890";
2642 char str1a[] = "123456\\\"789\\r";
2643 char str1b[] = "12345678\\r9";
2644 char str1c[] = "12345678\\x0a_9";
2645 char str1d[] = "12345678\\007_9";
2646 char str1e[] = "123456789\\\\";
2647
2648 char str2[] = "1234567890\\xw";
2649 char str3[] = "1234567890\\xw99";
2650 char str4[] = "1234567890\\0ww";
2651 char str5[] = "12345\\g67890";
2652 char str6[] = "1234567890\\009a";
2653
2654 char *s, *p, *q;
2655 size_t lo, lr;
2656
2657 s = SH_ALLOC(64); sl_strlcpy(s, str1, 64); p = s; lo = strlen(s); lr = lo;
2658 q = sh_files_C_dequote(s, &lr);
2659 CuAssertPtrNotNull(tc, q);
2660 CuAssertTrue(tc, p == q);
2661 CuAssertTrue(tc, lr == lo);
2662
2663 s = SH_ALLOC(64); sl_strlcpy(s, str1a, 64); p = s; lo = strlen(s); lr = lo;
2664 q = sh_files_C_dequote(s, &lr);
2665 CuAssertPtrNotNull(tc, q);
2666 CuAssertTrue(tc, p != q);
2667 CuAssertTrue(tc, 0 == strcmp(q, "123456\"789\r"));
2668 CuAssertTrue(tc, lr == (lo-2));
2669
2670 s = SH_ALLOC(64); sl_strlcpy(s, str1b, 64); p = s; lo = strlen(s); lr = lo;
2671 q = sh_files_C_dequote(s, &lr);
2672 CuAssertPtrNotNull(tc, q);
2673 CuAssertTrue(tc, p != q);
2674 CuAssertTrue(tc, 0 == strcmp(q, "12345678\r9"));
2675 CuAssertTrue(tc, lr == (lo-1));
2676
2677 s = SH_ALLOC(64); sl_strlcpy(s, str1c, 64); p = s; lo = strlen(s); lr = lo;
2678 q = sh_files_C_dequote(s, &lr);
2679 CuAssertPtrNotNull(tc, q);
2680 CuAssertTrue(tc, p != q);
2681 CuAssertTrue(tc, 0 == strcmp(q, "12345678\x0a_9"));
2682 CuAssertTrue(tc, lr == (lo-3));
2683
2684 s = SH_ALLOC(64); sl_strlcpy(s, str1d, 64); p = s; lo = strlen(s); lr = lo;
2685 q = sh_files_C_dequote(s, &lr);
2686 CuAssertPtrNotNull(tc, q);
2687 CuAssertTrue(tc, p != q);
2688 CuAssertTrue(tc, 0 == strcmp(q, "12345678\007_9"));
2689 CuAssertTrue(tc, lr == (lo-3));
2690
2691 s = SH_ALLOC(64); sl_strlcpy(s, str1e, 64); p = s; lo = strlen(s); lr = lo;
2692 q = sh_files_C_dequote(s, &lr);
2693 CuAssertPtrNotNull(tc, q);
2694 CuAssertTrue(tc, p != q);
2695 CuAssertTrue(tc, 0 == strcmp(q, "123456789\\"));
2696 CuAssertTrue(tc, lr == (lo-1));
2697
2698 s = SH_ALLOC(64); sl_strlcpy(s, str2, 64); p = s; lo = strlen(s); lr = lo;
2699 q = sh_files_C_dequote(s, &lr);
2700 CuAssertTrue(tc, q == NULL);
2701 CuAssertTrue(tc, lr == 0);
2702
2703 s = SH_ALLOC(64); sl_strlcpy(s, str3, 64); p = s; lo = strlen(s); lr = lo;
2704 q = sh_files_C_dequote(s, &lr);
2705 CuAssertTrue(tc, q == NULL);
2706 CuAssertTrue(tc, lr == 0);
2707
2708 s = SH_ALLOC(64); sl_strlcpy(s, str4, 64); p = s; lo = strlen(s); lr = lo;
2709 q = sh_files_C_dequote(s, &lr);
2710 CuAssertTrue(tc, q == NULL);
2711 CuAssertTrue(tc, lr == 0);
2712
2713 s = SH_ALLOC(64); sl_strlcpy(s, str5, 64); p = s; lo = strlen(s); lr = lo;
2714 q = sh_files_C_dequote(s, &lr);
2715 CuAssertTrue(tc, q == NULL);
2716 CuAssertTrue(tc, lr == 0);
2717
2718 s = SH_ALLOC(64); sl_strlcpy(s, str6, 64); p = s; lo = strlen(s); lr = lo;
2719 q = sh_files_C_dequote(s, &lr);
2720 CuAssertTrue(tc, q == NULL);
2721 CuAssertTrue(tc, lr == 0);
2722
2723 return;
2724#else
2725 (void) tc; /* fix compiler warning */
2726 return;
2727#endif
2728}
2729#endif
2730
Note: See TracBrowser for help on using the repository browser.