source: trunk/src/sh_files.c@ 381

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

Fix for ticket #279 (checksum flip with --enable-suidcheck).

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