source: trunk/src/sh_files.c@ 383

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

Fix for ticket #281 (warnings from clang static analyzer).

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