source: trunk/src/sh_files.c@ 358

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

Patch for ticket #261: show policy for checked files in verbose mode.

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