source: trunk/src/sh_files.c@ 309

Last change on this file since 309 was 307, checked in by katerina, 14 years ago

Fix for ticket #229 (malfunction on CentOS 4.8 / gcc4), documentation update.

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