source: trunk/src/sh_hash.c@ 377

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

Patch for ticket #265 (inotify support).

File size: 102.5 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000, 2001, 2002 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/* define this if you want version 1.3 style database file */
23/* #define OLD_BUG */
24
25/* make sure state changes of a file are always reported, even
26 * with reportonlyonce=true
27 */
28/* #define REPLACE_OLD *//* moved to samhain.h */
29
30#include <stdlib.h>
31#include <string.h>
32#include <stdio.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <unistd.h>
36
37#ifdef MAJOR_IN_MKDEV
38#include <sys/mkdev.h>
39#else
40#ifdef MAJOR_IN_SYSMACROS
41#include <sys/sysmacros.h>
42#endif
43#endif
44
45#ifdef HAVE_MEMORY_H
46#include <memory.h>
47#endif
48
49#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
50
51#include "sh_hash.h"
52#include "sh_utils.h"
53#include "sh_error.h"
54#include "sh_tiger.h"
55#include "sh_gpg.h"
56#include "sh_unix.h"
57#include "sh_files.h"
58#include "sh_ignore.h"
59#include "sh_pthread.h"
60
61#if defined(SH_WITH_CLIENT)
62#include "sh_forward.h"
63#endif
64
65
66#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
67
68
69#undef FIL__
70#define FIL__ _("sh_hash.c")
71
72SH_MUTEX_STATIC(mutex_hash,PTHREAD_MUTEX_INITIALIZER);
73
74const char notalink[2] = { '-', '\0' };
75
76static char * all_items (file_type * theFile, char * fileHash, int is_new);
77
78#define QUOTE_CHAR '='
79
80char * unquote_string (const char * str, size_t len)
81{
82 int i = 0, t1, t2;
83 char * tmp = NULL;
84 size_t l2, j, k = 0;
85
86 SL_ENTER(_("unquote_string"));
87
88 if (str != NULL)
89 {
90 l2 = len - 2;
91 tmp = SH_ALLOC(len + 1);
92
93 for (j = 0; j <= len; ++j)
94 {
95 if (str[j] != QUOTE_CHAR)
96 {
97 tmp[k] = str[j];
98 }
99 else if (str[j] == QUOTE_CHAR && j < l2)
100 {
101 t1 = sh_util_hexchar(str[j+1]);
102 t2 = sh_util_hexchar(str[j+2]);
103 if ((t1|t2) >= 0)
104 {
105 i = 16 * t1 + t2;
106 tmp[k] = i;
107 j += 2;
108 }
109 else
110 {
111 tmp[k] = str[j];
112 }
113 }
114 else
115 tmp[k] = str[j];
116 ++k;
117 }
118 }
119 SL_RETURN(tmp, _("unquote_string"));
120}
121
122
123static char * int2hex (unsigned char i, char * i2h)
124{
125 static char hexchars[] = "0123456789ABCDEF";
126
127 i2h[0] = hexchars[(((i) & 0xF0) >> 4)]; /* high */
128 i2h[1] = hexchars[((i) & 0x0F)]; /* low */
129
130 return i2h;
131}
132
133
134char * quote_string (const char * str, size_t len)
135{
136 char * tmp;
137 char * tmp2;
138 size_t l2, j, i = 0, k = 0;
139 char i2h[2];
140
141 SL_ENTER(_("quote_string"));
142
143 if (str == NULL)
144 {
145 SL_RETURN(NULL, _("quote_string"));
146 }
147
148 for (j = 0; j < len; ++j)
149 if (str[j] == '\n' || str[j] == QUOTE_CHAR) ++i;
150
151 l2 = len + 1;
152 if (sl_ok_muls(3, i) && sl_ok_adds(l2, (3*i)))
153 {
154 tmp = SH_ALLOC(len + 1 + 3*i);
155 }
156 else
157 {
158 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
159 _("integer overflow"),
160 _("quote_string"));
161 SL_RETURN(NULL, _("quote_string"));
162 }
163
164 for (j = 0; j <= len; ++j)
165 {
166 if (str[j] == '\n')
167 {
168 tmp2 = int2hex((unsigned char) '\n', i2h); /* was 'n', fixed in 1.5.4 */
169 tmp[k] = QUOTE_CHAR; ++k;
170 tmp[k] = tmp2[0]; ++k;
171 tmp[k] = tmp2[1];
172 }
173 else if (str[j] == QUOTE_CHAR)
174 {
175 tmp2 = int2hex((unsigned char) QUOTE_CHAR, i2h);
176 tmp[k] = QUOTE_CHAR; ++k;
177 tmp[k] = tmp2[0]; ++k;
178 tmp[k] = tmp2[1];
179 }
180 else
181 {
182 tmp[k] = str[j];
183 }
184 ++k;
185 }
186 SL_RETURN(tmp, _("quote_string"));
187}
188
189static UINT32 * swap_32 (UINT32 * iptr)
190{
191#ifdef WORDS_BIGENDIAN
192 unsigned char swap;
193 unsigned char * ii = (unsigned char *) iptr;
194 swap = ii[0]; ii[0] = ii[3]; ii[3] = swap;
195 swap = ii[1]; ii[1] = ii[2]; ii[2] = swap;
196 return iptr;
197#else
198 return iptr;
199#endif
200}
201
202static UINT64 * swap_64 (UINT64 * iptr)
203{
204#ifdef WORDS_BIGENDIAN
205#ifdef UINT64_IS_32
206 swap_32 ((UINT32*) iptr);
207#else
208 unsigned char swap;
209 unsigned char * ii = (unsigned char *) iptr;
210 swap = ii[0]; ii[0] = ii[7]; ii[7] = swap;
211 swap = ii[1]; ii[1] = ii[6]; ii[6] = swap;
212 swap = ii[2]; ii[2] = ii[5]; ii[5] = swap;
213 swap = ii[3]; ii[3] = ii[4]; ii[4] = swap;
214#endif
215 return iptr;
216#else
217 return iptr;
218#endif
219}
220
221static unsigned short * swap_short (unsigned short * iptr)
222{
223#ifdef WORDS_BIGENDIAN
224 if (sizeof(short) == 4)
225 swap_32 ((UINT32*) iptr);
226 else
227 {
228 /* alignment problem */
229 unsigned char swap;
230 static unsigned short ooop;
231 unsigned char * ii;
232 ooop = *iptr;
233 ii = (unsigned char *) &ooop;
234 /* printf("SWAP0: %hd %d\n", *iptr, sizeof(unsigned short)); */
235 swap = ii[0]; ii[0] = ii[1]; ii[1] = swap;
236 /* printf("SWAP1: %hd\n", (unsigned short) ooop); */
237#ifndef OLD_BUG
238 return &ooop;
239#endif
240 }
241 return iptr;
242#else
243 return iptr;
244#endif
245}
246
247
248typedef struct store_info {
249
250 UINT32 mode;
251 UINT32 linkmode;
252
253 UINT64 dev;
254 UINT64 rdev;
255 UINT32 hardlinks;
256 UINT32 ino;
257 UINT64 size;
258 UINT64 atime;
259 UINT64 mtime;
260 UINT64 ctime;
261 UINT32 owner;
262 UINT32 group;
263
264#ifdef OLD_BUG
265#if defined(__linux__)
266 UINT32 attributes;
267 char c_attributes[ATTRBUF_SIZE];
268#endif
269#else
270 /* #if defined(__linux__) */
271 UINT32 attributes;
272 char c_attributes[ATTRBUF_SIZE];
273 /* endif */
274#endif
275 unsigned short mark;
276 char c_owner[USER_MAX+2];
277 char c_group[GROUP_MAX+2];
278 char c_mode[CMODE_SIZE];
279 char checksum[KEY_LEN+1];
280} sh_filestore_t;
281
282typedef struct file_info {
283 sh_filestore_t theFile;
284 char * fullpath;
285 char * linkpath;
286 char * attr_string;
287 int fflags;
288 unsigned long modi_mask;
289 struct file_info * next;
290} sh_file_t;
291
292 static const char *policy[] = {
293 N_("[]"),
294 N_("[ReadOnly]"),
295 N_("[LogFiles]"),
296 N_("[GrowingLogs]"),
297 N_("[IgnoreNone]"),
298 N_("[IgnoreAll]"),
299 N_("[Attributes]"),
300 N_("[User0]"),
301 N_("[User1]"),
302 N_("[User2]"),
303 N_("[User3]"),
304 N_("[User4]"),
305 N_("[Prelink]"),
306 NULL
307 };
308
309const char * sh_hash_getpolicy(int class)
310{
311 if (class > 0 && class < SH_ERR_T_DIR)
312 return _(policy[class]);
313 return _("[indef]");
314}
315
316/**********************************
317 *
318 * hash table functions
319 *
320 **********************************
321 */
322
323#include "sh_hash.h"
324
325/* must fit an int */
326/* #define TABSIZE 2048 */
327#define TABSIZE 65536
328
329/* must fit an unsigned short */
330/* changed for V0.8, as the */
331/* database format has changed */
332
333/* changed again for V0.9 */
334/* #define REC_MAGIC 19 */
335/* changed again for V1.3 */
336#ifdef OLD_BUG
337#define REC_MAGIC 20
338#else
339/* changed again for V1.4 */
340#define REC_MAGIC 21
341#endif
342
343#define REC_FLAGS_ATTR (1<<8)
344#define REC_FLAGS_MASK 0xFF00
345
346/**************************************************************
347 *
348 * create a file_type from a sh_file_t
349 *
350 **************************************************************/
351static file_type * sh_hash_create_ft (const sh_file_t * p, char * fileHash)
352{
353 file_type * theFile;
354
355 SL_ENTER(_("sh_hash_create_ft"));
356
357 theFile = SH_ALLOC(sizeof(file_type));
358
359 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
360 theFile->mode = p->theFile.mode;
361#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
362 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, ATTRBUF_SIZE);
363 theFile->attributes = p->theFile.attributes;
364#endif
365
366 sl_strlcpy(theFile->fullpath, p->fullpath, PATH_MAX);
367 if (p->linkpath != NULL /* && theFile->c_mode[0] == 'l' */)
368 {
369 theFile->link_path = sh_util_strdup(p->linkpath);
370 }
371 else
372 {
373 theFile->link_path = NULL;
374 }
375 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
376
377 theFile->mtime = p->theFile.mtime;
378 theFile->ctime = p->theFile.ctime;
379 theFile->atime = p->theFile.atime;
380
381 theFile->size = p->theFile.size;
382
383 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
384 theFile->group = p->theFile.group;
385 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
386 theFile->owner = p->theFile.owner;
387
388 theFile->ino = p->theFile.ino;
389 theFile->rdev = p->theFile.rdev;
390 theFile->dev = p->theFile.dev;
391 theFile->hardlinks = p->theFile.hardlinks;
392
393 if (p->attr_string)
394 theFile->attr_string = sh_util_strdup(p->attr_string);
395 else
396 theFile->attr_string = NULL;
397
398 SL_RETURN((theFile), _("sh_hash_create_ft"));
399}
400
401struct two_sh_file_t {
402 sh_file_t * prev;
403 sh_file_t * this;
404};
405
406static sh_file_t * hashsearch (const char * s);
407static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index);
408
409static sh_file_t * tab[TABSIZE];
410
411/**************************************************************
412 *
413 * compute hash function
414 *
415 **************************************************************/
416
417static int hashfunc(const char *s)
418{
419 unsigned int n = 0;
420
421 for ( ; *s; s++)
422 n = 31 * n + *s;
423
424 return n & (TABSIZE - 1); /* % TABSIZE */;
425}
426
427
428int hashreport_missing( char *fullpath, int level)
429{
430 sh_file_t * p;
431 char * tmp;
432 char fileHash[KEY_LEN + 1];
433 file_type * theFile;
434 char * str;
435 char hashbuf[KEYBUF_SIZE];
436 volatile int retval;
437
438 /* -------- find the entry for the file ---------------- */
439
440 SH_MUTEX_LOCK(mutex_hash);
441
442 retval = 0;
443
444 if (sl_strlen(fullpath) <= MAX_PATH_STORE)
445 p = hashsearch(fullpath);
446 else
447 p = hashsearch( sh_tiger_hash(fullpath,
448 TIGER_DATA,
449 sl_strlen(fullpath),
450 hashbuf, sizeof(hashbuf))
451 );
452 if (p == NULL)
453 {
454 retval = -1;
455 goto unlock_and_return;
456 }
457
458 theFile = sh_hash_create_ft (p, fileHash);
459 str = all_items(theFile, fileHash, 0);
460 tmp = sh_util_safe_name(fullpath);
461
462 SH_MUTEX_LOCK(mutex_thread_nolog);
463 sh_error_handle (level, FIL__, __LINE__, 0,
464 MSG_FI_MISS2, tmp, str);
465 SH_MUTEX_UNLOCK(mutex_thread_nolog);
466
467 SH_FREE(tmp);
468 SH_FREE(str);
469 if (theFile->attr_string) SH_FREE(theFile->attr_string);
470 if (theFile->link_path) SH_FREE(theFile->link_path);
471 SH_FREE(theFile);
472
473 unlock_and_return:
474 ; /* 'label at end of compound statement */
475 SH_MUTEX_UNLOCK(mutex_hash);
476
477 return retval;
478}
479
480
481/**************************************************************
482 *
483 * search for files not visited, and check whether they exist
484 *
485 **************************************************************/
486static sh_file_t * delete_db_entry(sh_file_t *p)
487{
488 if (p->fullpath)
489 {
490 SH_FREE(p->fullpath);
491 p->fullpath = NULL;
492 }
493 if (p->linkpath)
494 {
495 if (p->linkpath != notalink)
496 SH_FREE(p->linkpath);
497 p->linkpath = NULL;
498 }
499 if (p->attr_string)
500 {
501 SH_FREE(p->attr_string);
502 p->attr_string = NULL;
503 }
504 SH_FREE(p);
505 return NULL;
506}
507
508static void hash_unvisited (int j,
509 sh_file_t *prev, sh_file_t *p, ShErrLevel level)
510{
511 struct stat buf;
512 int i;
513 char * tmp;
514 char * ptr;
515 char fileHash[KEY_LEN + 1];
516 file_type * theFile;
517
518 char * str;
519
520
521 SL_ENTER(_("hash_unvisited"));
522
523 if (p->next != NULL)
524 hash_unvisited (j, p, p->next, level);
525
526 if (p->fullpath == NULL)
527 {
528 SL_RET0(_("hash_unvisited"));
529 }
530
531 /* Not a fully qualified path, i.e. some info stored by some module
532 */
533 if (p->fullpath[0] != '/')
534 {
535 SL_RET0(_("hash_unvisited"));
536 }
537
538 /* visited flag not set: not seen;
539 * checked flag set: not seen (i.e. missing), and already checked
540 * reported flag not set: not reported yet
541 * allignore flag not set: not under IgnoreAll
542 *
543 * Files/directories under IgnoreAll are noticed as missing already
544 * during the file check.
545 */
546 if (((!SH_FFLAG_VISITED_SET(p->fflags)) || SH_FFLAG_CHECKED_SET(p->fflags))
547 && (!SH_FFLAG_REPORTED_SET(p->fflags))
548 && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)))
549 {
550 i = retry_lstat(FIL__, __LINE__, p->fullpath, &buf);
551
552 /* if file does not exist
553 */
554 if (0 != i)
555 {
556 ptr = sh_util_dirname (p->fullpath);
557 if (ptr)
558 {
559 /* If any of the parent directories is under IgnoreAll
560 */
561 if (0 != sh_files_is_allignore(ptr))
562 level = ShDFLevel[SH_LEVEL_ALLIGNORE];
563 SH_FREE(ptr);
564 }
565
566 /* Only report if !SH_FFLAG_CHECKED_SET
567 */
568 if (!SH_FFLAG_CHECKED_SET(p->fflags))
569 {
570 if (S_FALSE == sh_ignore_chk_del(p->fullpath))
571 {
572 tmp = sh_util_safe_name(p->fullpath);
573
574 theFile = sh_hash_create_ft (p, fileHash);
575 str = all_items(theFile, fileHash, 0);
576 sh_error_handle (level, FIL__, __LINE__, 0,
577 MSG_FI_MISS2, tmp, str);
578 SH_FREE(str);
579 if (theFile->attr_string) SH_FREE(theFile->attr_string);
580 if (theFile->link_path) SH_FREE(theFile->link_path);
581 SH_FREE(theFile);
582
583 SH_FREE(tmp);
584 }
585 }
586
587 /* We rewrite the db on update, thus we need to keep this
588 * if the user does not want to purge it from the db.
589 */
590
591 if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) ||
592 (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(p->fullpath)))
593 {
594#ifdef REPLACE_OLD
595 /* Remove the old entry
596 */
597 if (prev == p)
598 tab[j] = p->next;
599 else
600 prev->next = p->next;
601
602 p = delete_db_entry(p);
603
604 SL_RET0(_("hash_unvisited"));
605#else
606 SET_SH_FFLAG_REPORTED(p->fflags);
607#endif
608 }
609 }
610 }
611
612 else if (SH_FFLAG_VISITED_SET(p->fflags) && SH_FFLAG_REPORTED_SET(p->fflags)
613 && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)))
614 {
615 if (S_FALSE == sh_ignore_chk_new(p->fullpath))
616 {
617 tmp = sh_util_safe_name(p->fullpath);
618
619 theFile = sh_hash_create_ft (p, fileHash);
620 str = all_items(theFile, fileHash, 0);
621 sh_error_handle (level, FIL__, __LINE__, 0,
622 MSG_FI_MISS2, tmp, str);
623 SH_FREE(str);
624 if (theFile->attr_string)
625 SH_FREE(theFile->attr_string);
626 SH_FREE(theFile);
627
628 SH_FREE(tmp);
629 }
630
631 CLEAR_SH_FFLAG_REPORTED(p->fflags);
632 }
633
634 if (sh.flag.reportonce == S_FALSE)
635 CLEAR_SH_FFLAG_REPORTED(p->fflags);
636
637 CLEAR_SH_FFLAG_VISITED(p->fflags);
638 CLEAR_SH_FFLAG_CHECKED(p->fflags);
639
640 SL_RET0(_("hash_unvisited"));
641}
642
643
644
645/*********************************************************************
646 *
647 * Search for files in the database that have been deleted from disk.
648 *
649 *********************************************************************/
650void sh_hash_unvisited (ShErrLevel level)
651{
652 int i;
653
654 SL_ENTER(_("sh_hash_unvisited"));
655
656 SH_MUTEX_LOCK(mutex_hash);
657 for (i = 0; i < TABSIZE; ++i)
658 {
659 if (tab[i] != NULL)
660 hash_unvisited (i, tab[i], tab[i], level);
661 }
662 SH_MUTEX_UNLOCK(mutex_hash);
663
664 SL_RET0(_("hash_unvisited"));
665}
666
667/*********************************************************************
668 *
669 * Remove a single file from the database.
670 *
671 *********************************************************************/
672void sh_hash_remove (const char * path)
673{
674 struct two_sh_file_t entries;
675 int index;
676
677 SL_ENTER(_("sh_hash_remove"));
678
679 SH_MUTEX_LOCK(mutex_hash);
680
681 if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) ||
682 (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(path)))
683 {
684 if (0 == hashsearch_prev (path, &entries, &index))
685 {
686 sh_file_t * p = entries.this;
687#ifdef REPLACE_OLD
688 /* Remove the old entry
689 */
690 if (entries.prev == p)
691 tab[index] = p->next;
692 else
693 entries.prev->next = p->next;
694
695 p = delete_db_entry(p);
696
697 goto end;
698#else
699 SET_SH_FFLAG_REPORTED(p->fflags);
700#endif
701 }
702 }
703
704 end:
705 ; /* 'label at end of compound statement' */
706 SH_MUTEX_UNLOCK(mutex_hash);
707
708 SL_RET0(_("sh_hash_remove"));
709}
710
711
712/*********************************************************************
713 *
714 * Search for unvisited entries in the database, custom error handler.
715 *
716 *********************************************************************/
717void sh_hash_unvisited_custom (char prefix, void(*handler)(const char * key))
718{
719 int i;
720 sh_file_t *p = NULL;
721 sh_file_t *prev = NULL;
722 sh_file_t *next = NULL;
723
724 SL_ENTER(_("sh_hash_unvisited_custom"));
725
726 SH_MUTEX_LOCK(mutex_hash);
727 for (i = 0; i < TABSIZE; ++i)
728 {
729 if (tab[i] != NULL)
730 {
731 p = tab[i]; prev = p;
732
733 do
734 {
735 next = p->next;
736
737 if (p->fullpath &&
738 prefix == p->fullpath[0])
739 {
740 if ((!SH_FFLAG_VISITED_SET(p->fflags))
741 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
742 {
743 handler(p->fullpath);
744
745 if (!SH_FFLAG_CHECKED_SET(p->fflags))
746 {
747 /* delete */
748 if (tab[i] == p)
749 {
750 tab[i] = p->next;
751 prev = tab[i];
752 next = prev;
753 }
754 else
755 {
756 prev->next = p->next;
757 next = prev->next;
758 }
759
760 p = delete_db_entry(p);
761 }
762 }
763 if (p)
764 {
765 CLEAR_SH_FFLAG_VISITED(p->fflags);
766 CLEAR_SH_FFLAG_CHECKED(p->fflags);
767 }
768 }
769 if (p)
770 prev = p;
771 p = next;
772 }
773 while (p);
774 }
775 }
776 SH_MUTEX_UNLOCK(mutex_hash);
777
778 SL_RET0(_("hash_unvisited_custom"));
779}
780
781
782/**********************************************************************
783 *
784 * delete hash array
785 *
786 **********************************************************************/
787static void hash_kill (sh_file_t *p)
788{
789 SL_ENTER(_("hash_kill"));
790
791 if (p == NULL)
792 SL_RET0(_("hash_kill"));
793
794 if (p->next != NULL)
795 hash_kill (p->next);
796
797 if (p->fullpath)
798 {
799 SH_FREE(p->fullpath);
800 p->fullpath = NULL;
801 }
802 if (p->linkpath)
803 {
804 if (p->linkpath != notalink)
805 SH_FREE(p->linkpath);
806 p->linkpath = NULL;
807 }
808 if (p->attr_string)
809 {
810 SH_FREE(p->attr_string);
811 p->attr_string = NULL;
812 }
813 SH_FREE(p);
814 p = NULL;
815 SL_RET0(_("hash_kill"));
816}
817
818
819/***********************************************************************
820 *
821 * get info out of hash array
822 *
823 ***********************************************************************/
824static sh_file_t * hashsearch (const char * s)
825{
826 sh_file_t * p;
827
828 SL_ENTER(_("hashsearch"));
829
830 if (s)
831 {
832 for (p = tab[hashfunc(s)]; p; p = p->next)
833 if ((p->fullpath != NULL) && (0 == strcmp(s, p->fullpath)))
834 SL_RETURN( p, _("hashsearch"));
835 }
836 SL_RETURN( NULL, _("hashsearch"));
837}
838
839static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index)
840{
841 sh_file_t * this;
842 sh_file_t * prev = NULL;
843
844 SL_ENTER(_("hashsearch_prev"));
845
846 if (s)
847 {
848 *index = hashfunc(s);
849
850 this = tab[*index];
851
852 prev = this;
853
854 if (this)
855 {
856 do {
857
858 if ((this->fullpath != NULL) && (0 == strcmp(s, this->fullpath)))
859 {
860 a->prev = prev;
861 a->this = this;
862
863 SL_RETURN( 0, _("hashsearch_prev"));
864 }
865
866 prev = this;
867 this = this->next;
868
869 } while(this);
870 }
871 }
872 SL_RETURN( -1, _("hashsearch"));
873}
874
875
876/***********************************************************************
877 *
878 * insert into hash array
879 *
880 ***********************************************************************/
881static void hashinsert (sh_file_t * s)
882{
883 sh_file_t * p;
884 sh_file_t * q;
885 int key;
886
887 SL_ENTER(_("hashinsert"));
888
889 key = hashfunc(s->fullpath);
890
891 if (tab[key] == NULL)
892 {
893 tab[key] = s;
894 tab[key]->next = NULL;
895 SL_RET0(_("hashinsert"));
896 }
897 else
898 {
899 p = tab[key];
900 while (1)
901 {
902 if (p && p->fullpath &&
903 0 == strcmp(s->fullpath, p->fullpath))
904 {
905 q = p->next;
906 SH_FREE(p->fullpath);
907 if(p->linkpath && p->linkpath != notalink)
908 SH_FREE(p->linkpath);
909 if(p->attr_string)
910 SH_FREE(p->attr_string);
911 memcpy(p, s, sizeof(sh_file_t));
912 p->next = q;
913 SH_FREE(s);
914 s = NULL;
915 SL_RET0(_("hashinsert"));
916 }
917 else
918 if (p->next == NULL)
919 {
920 p->next = s;
921 p->next->next = NULL;
922 SL_RET0(_("hashinsert"));
923 }
924 p = p->next;
925 }
926 }
927 /* notreached */
928}
929
930
931/******************************************************************
932 *
933 * Get a single line
934 *
935 ******************************************************************/
936static FILE * sh_fin_fd = NULL;
937
938static int sh_hash_getline (FILE * fd, char * line, int sizeofline)
939{
940 register int n = 0;
941 char * res;
942
943 if (sizeofline < 2) {
944 if (sizeofline > 0) line[0] = '\0';
945 return 0;
946 }
947 res = fgets(line, sizeofline, fd);
948 if (res == NULL)
949 {
950 line[0] = '\0';
951 return -1;
952 }
953 n = strlen(line);
954 if (n > 0) {
955 --n;
956 line[n] = '\0'; /* remove terminating '\n' */
957 }
958 return n;
959}
960
961static void sh_hash_getline_end (void)
962{
963 sl_fclose (FIL__, __LINE__, sh_fin_fd);
964 sh_fin_fd = NULL;
965 return;
966}
967
968/******************************************************************
969 *
970 * ------- Check functions -------
971 *
972 ******************************************************************/
973
974static int IsInit = 0;
975
976
977/******************************************************************
978 *
979 * Fast forward to start of data
980 *
981 ******************************************************************/
982int sh_hash_setdataent (SL_TICKET fd, char * line, int size, const char * file)
983{
984 long i;
985 extern int get_the_fd (SL_TICKET ticket);
986
987 SL_ENTER(_("sh_hash_setdataent"));
988
989 sl_rewind (fd);
990
991 if (sh_fin_fd != NULL)
992 {
993 sl_fclose (FIL__, __LINE__, sh_fin_fd);
994 sh_fin_fd = NULL;
995 }
996
997 sh_fin_fd = fdopen(dup(get_the_fd(fd)), "rb");
998 if (!sh_fin_fd)
999 {
1000 dlog(1, FIL__, __LINE__,
1001 _("The file signature database: %s is not readable.\n"),
1002 (NULL == file) ? _("(null)") : file);
1003 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1004 ( (NULL == file) ? _("(null)") : file)
1005 );
1006 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1007 }
1008
1009 while (1)
1010 {
1011 i = sh_hash_getline (sh_fin_fd, line, size);
1012 if (i < 0 )
1013 {
1014 SH_FREE(line);
1015 dlog(1, FIL__, __LINE__,
1016 _("The file signature database: %s does not\ncontain any data, or the start-of-file marker is missing (unlikely,\nunless modified by hand).\n"),
1017 (NULL == file) ? _("(null)") : file);
1018
1019 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1020 ( (NULL == file) ? _("(null)") : file)
1021 );
1022 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1023 }
1024
1025#if defined(SH_STEALTH)
1026 if (0 == sl_strncmp (line, N_("[SOF]"), 5))
1027#else
1028 if (0 == sl_strncmp (line, _("[SOF]"), 5))
1029#endif
1030 break;
1031 }
1032 SL_RETURN( 1, _("sh_hash_setdataent"));
1033}
1034
1035static int sh_hash_setdataent_old (SL_TICKET fd, char * line, int size,
1036 char * file)
1037{
1038 long i;
1039
1040 SL_ENTER(_("sh_hash_setdataent_old"));
1041
1042 sl_rewind (fd);
1043
1044 while (1)
1045 {
1046 i = sh_unix_getline (fd, line, size-1);
1047 if (i < 0 )
1048 {
1049 SH_FREE(line);
1050 dlog(1, FIL__, __LINE__,
1051 _("The file signature database: %s does not\ncontain any data, or the start-of-file marker is missing (unlikely,\nunless modified by hand).\n"),
1052 (NULL == file) ? _("(null)") : file);
1053
1054 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1055 ( (NULL == file) ? _("(null)") : file)
1056 );
1057 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1058 }
1059
1060#if defined(SH_STEALTH)
1061 if (0 == sl_strncmp (line, N_("[SOF]"), 5))
1062#else
1063 if (0 == sl_strncmp (line, _("[SOF]"), 5))
1064#endif
1065 break;
1066 }
1067 SL_RETURN( 1, _("sh_hash_setdataent_old"));
1068}
1069
1070/******************************************************************
1071 *
1072 * Read next record
1073 *
1074 ******************************************************************/
1075sh_file_t * sh_hash_getdataent (SL_TICKET fd, char * line, int size)
1076{
1077 sh_file_t * p;
1078 sh_filestore_t ft;
1079 long i;
1080 size_t len;
1081 char * fullpath;
1082 char * linkpath;
1083 char * attr_string = NULL;
1084 char * tmp;
1085
1086 SL_ENTER(_("sh_hash_getdataent"));
1087
1088 (void) fd;
1089
1090 /* Read next record -- Part One
1091 */
1092 p = SH_ALLOC(sizeof(sh_file_t));
1093
1094 i = fread (&ft, sizeof(sh_filestore_t), 1, sh_fin_fd);
1095 /* i = sl_read(fd, &ft, sizeof(sh_filestore_t)); */
1096 /* if ( SL_ISERROR(i) || i == 0) */
1097 if (i < 1)
1098 {
1099 SH_FREE(p);
1100 SL_RETURN( NULL, _("sh_hash_getdataent"));
1101 }
1102
1103 swap_32(&(ft.mode));
1104 swap_32(&(ft.linkmode));
1105 swap_64(&(ft.dev));
1106 swap_64(&(ft.rdev));
1107 swap_32(&(ft.hardlinks));
1108 swap_32(&(ft.ino));
1109 swap_64(&(ft.size));
1110 swap_64(&(ft.atime));
1111 swap_64(&(ft.mtime));
1112 swap_64(&(ft.ctime));
1113 swap_32(&(ft.owner));
1114 swap_32(&(ft.group));
1115#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1116 swap_32(&(ft.attributes));
1117#endif
1118#ifdef OLD_BUG
1119 swap_short(&(ft.mark));
1120#else
1121 ft.mark = *(swap_short(&(ft.mark)));
1122#endif
1123
1124 if ((ft.mark & ~REC_FLAGS_MASK) != REC_MAGIC)
1125 {
1126 SH_FREE(p);
1127 SL_RETURN( NULL, _("sh_hash_getdataent"));
1128 }
1129
1130 /* Read next record -- Part Two -- Fullpath
1131 */
1132 i = sh_hash_getline (sh_fin_fd, line, size);
1133 if (i <= 0 )
1134 {
1135 SH_FREE(line);
1136 SH_FREE(p);
1137 dlog(1, FIL__, __LINE__,
1138 _("There is a corrupt record in the file signature database: %s\nThe file path is missing.\n"),
1139 (NULL == file_path('D', 'R'))? _("(null)"):file_path('D', 'R'));
1140 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1141 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1142 file_path('D', 'R'))
1143 );
1144 aud_exit (FIL__, __LINE__,EXIT_FAILURE);
1145 }
1146
1147 tmp = unquote_string (line, i);
1148 len = sl_strlen(tmp)+1;
1149 fullpath = SH_ALLOC(len);
1150 (void) sl_strlcpy (fullpath, tmp, len);
1151 if (tmp)
1152 SH_FREE(tmp);
1153 if (fullpath[len-2] == '\n')
1154 fullpath[len-2] = '\0';
1155
1156 /* Read next record -- Part Three -- Linkpath
1157 */
1158 i = sh_hash_getline (sh_fin_fd, line, size);
1159 if (i <= 0 )
1160 {
1161 SH_FREE(line);
1162 SH_FREE(fullpath);
1163 SH_FREE(p);
1164 dlog(1, FIL__, __LINE__,
1165 _("There is a corrupt record in the file signature database: %s\nThe link path (or its placeholder) is missing.\n"),
1166 (NULL == file_path('D', 'R'))? _("(null)"):file_path('D', 'R'));
1167 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1168 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1169 file_path('D', 'R'))
1170 );
1171 aud_exit (FIL__, __LINE__,EXIT_FAILURE);
1172 }
1173
1174 tmp = unquote_string (line, i);
1175
1176 if ( tmp && tmp[0] == '-' &&
1177 (tmp[1] == '\0' || (tmp[1] == '\n' && tmp[2] == '\0')))
1178 {
1179 linkpath = (char *)notalink;
1180 }
1181 else
1182 {
1183 len = sl_strlen(tmp);
1184 linkpath = sh_util_strdup_l(tmp, len);
1185 if (len > 0 && linkpath[len-1] == '\n')
1186 linkpath[len-1] = '\0';
1187 }
1188
1189 if (tmp)
1190 SH_FREE(tmp);
1191
1192 /* Read next record -- Part Four -- attr_string
1193 */
1194 if ((ft.mark & REC_FLAGS_ATTR) != 0)
1195 {
1196 i = sh_hash_getline (sh_fin_fd, line, size);
1197 if (i <= 0 )
1198 {
1199 SH_FREE(line);
1200 SH_FREE(fullpath);
1201 if (linkpath != notalink)
1202 SH_FREE(linkpath);
1203 SH_FREE(p);
1204 dlog(1, FIL__, __LINE__,
1205 _("There is a corrupt record in the file signature database: %s\nThe attribute string is missing.\n"),
1206 (NULL == file_path('D', 'R'))? _("(null)"):file_path('D', 'R'));
1207 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1208 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1209 file_path('D', 'R'))
1210 );
1211 aud_exit (FIL__, __LINE__,EXIT_FAILURE);
1212 }
1213
1214 tmp = unquote_string (line, i);
1215
1216 len = sl_strlen(tmp)+1;
1217 attr_string = SH_ALLOC(len);
1218 (void) sl_strlcpy (attr_string, tmp, len);
1219 if (tmp)
1220 SH_FREE(tmp);
1221 if (attr_string[len-2] == '\n')
1222 attr_string[len-2] = '\0';
1223 }
1224
1225 /* Read next record -- Part Four -- Decode
1226 */
1227#if defined(SH_STEALTH)
1228 sh_do_decode(fullpath, sl_strlen(fullpath));
1229
1230#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1231 sh_do_decode(ft.c_attributes, sl_strlen(ft.c_attributes));
1232#endif
1233
1234 sh_do_decode(ft.c_mode, sl_strlen(ft.c_mode));
1235 sh_do_decode(ft.c_owner, sl_strlen(ft.c_owner));
1236 sh_do_decode(ft.c_group, sl_strlen(ft.c_group));
1237 sh_do_decode(ft.checksum, sl_strlen(ft.checksum));
1238
1239
1240 if (ft.c_mode[0] == 'l' && linkpath != notalink)
1241 {
1242 sh_do_decode(linkpath, sl_strlen(linkpath));
1243 }
1244 if ((ft.mark & REC_FLAGS_ATTR) != 0)
1245 {
1246 sh_do_decode(attr_string, sl_strlen(attr_string));
1247 }
1248#endif
1249
1250 memcpy( &(*p).theFile, &ft, sizeof(sh_filestore_t) );
1251
1252 /* init fflags, such that suid files in
1253 * database are recognized as such
1254 */
1255 {
1256 mode_t mode = (mode_t) ft.mode;
1257
1258 if (S_ISREG(mode) &&
1259 (0 !=(S_ISUID & mode) ||
1260#if defined(HOST_IS_LINUX)
1261 (0 !=(S_ISGID & mode) &&
1262 0 !=(S_IXGRP & mode))
1263#else
1264 0 !=(S_ISGID & mode)
1265#endif
1266 )
1267 )
1268 p->fflags = SH_FFLAG_SUIDCHK;
1269
1270 else
1271 p->fflags = 0;
1272 }
1273
1274 p->modi_mask = 0L;
1275 p->fullpath = fullpath;
1276 p->linkpath = linkpath;
1277
1278 p->attr_string = attr_string;
1279
1280 /* set to an invalid value
1281 */
1282 ft.mark = (REC_MAGIC + 5);
1283
1284 SL_RETURN( p, _("sh_hash_getdataent"));
1285}
1286
1287/******************************************************************
1288 *
1289 * Initialize
1290 *
1291 ******************************************************************/
1292void sh_hash_init ()
1293{
1294
1295#define FGETS_BUF 16384
1296
1297 sh_file_t * p;
1298 SL_TICKET fd;
1299 long i;
1300 int count = 0;
1301 char * line = NULL;
1302
1303#if defined(WITH_GPG) || defined(WITH_PGP)
1304 extern int get_the_fd (SL_TICKET ticket);
1305
1306 SL_TICKET fdTmp = (-1);
1307#endif
1308 char hashbuf[KEYBUF_SIZE];
1309
1310 volatile int retval = 0;
1311 volatile int exitval = EXIT_SUCCESS;
1312
1313 SL_ENTER(_("sh_hash_init"));
1314
1315 SH_MUTEX_LOCK(mutex_hash);
1316
1317 if (IsInit == 1)
1318 {
1319 goto unlock_and_return;
1320 }
1321
1322 fd = (-1);
1323
1324#if defined(SH_WITH_CLIENT)
1325
1326 /* Data file from Server
1327 */
1328
1329 if (fd == (-1) && 0 == sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
1330 {
1331 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_D_DSTART);
1332 fd = sh_forward_req_file(_("DATA"));
1333 if (SL_ISERROR(fd))
1334 {
1335 dlog(1, FIL__, __LINE__,
1336 _("Could not retrieve the file signature database from the server(errnum = %ld).\nPossible reasons include:\n - the server is not running,\n - session key negotiation failed (see the manual for proper setup), or\n - the server cannot access the file.\n"), fd);
1337 sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1,
1338 sh.prg_name);
1339 retval = 1; exitval = EXIT_FAILURE;
1340 goto unlock_and_return;
1341 }
1342 sl_rewind (fd);
1343
1344 sl_strlcpy (sh.data.hash,
1345 sh_tiger_hash (file_path('D', 'R'),
1346 fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
1347 KEY_LEN+1);
1348 sl_rewind (fd);
1349 }
1350 else
1351#endif
1352 /* Local data file
1353 */
1354
1355 if (fd == (-1))
1356 {
1357 if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__,
1358 file_path('D', 'R'), SL_YESPRIV)))
1359 {
1360 TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s>\n"),
1361 file_path('D', 'R')));
1362 dlog(1, FIL__, __LINE__,
1363 _("Could not open the local file signature database for reading because\nof the following error: %s (errnum = %ld)\nIf this is a permission problem, you need to change file permissions\nto make the file readable for the effective UID: %d\n"),
1364 sl_get_errmsg(), fd, (int) sl_ret_euid());
1365 sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1,
1366 sh.prg_name);
1367 retval = 1; exitval = EXIT_FAILURE;
1368 goto unlock_and_return;
1369 }
1370
1371 TPT(( 0, FIL__, __LINE__, _("msg=<Opened database: %s>\n"),
1372 file_path('D', 'R')));
1373
1374 if (0 != sl_strncmp(sh.data.hash,
1375 sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
1376 hashbuf, sizeof(hashbuf)),
1377 KEY_LEN)
1378 && sh.flag.checkSum != SH_CHECK_INIT)
1379 {
1380 dlog(1, FIL__, __LINE__,
1381 _("The checksum of the file signature database has changed since startup: %s -> %s\n"),
1382 sh.data.hash, sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
1383 hashbuf, sizeof(hashbuf)));
1384 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH,
1385 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1386 file_path('D', 'R') )
1387 );
1388 retval = 1; exitval = EXIT_FAILURE;
1389 goto unlock_and_return;
1390 }
1391 sl_rewind (fd);
1392
1393 } /* new 1.4.8 */
1394
1395 if (sig_termfast == 1) /* SIGTERM */
1396 {
1397 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1398 --sig_raised; --sig_urgent;
1399 retval = 1; exitval = EXIT_SUCCESS;
1400 goto unlock_and_return;
1401 }
1402
1403#if defined(WITH_GPG) || defined(WITH_PGP)
1404
1405 /* extract the data and copy to temporary file
1406 */
1407 fdTmp = sh_gpg_extract_signed(fd);
1408
1409 if (sig_termfast == 1) /* SIGTERM */
1410 {
1411 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1412 --sig_raised; --sig_urgent;
1413 retval = 1; exitval = EXIT_SUCCESS;
1414 goto unlock_and_return;
1415 }
1416
1417 sl_close(fd);
1418 fd = fdTmp;
1419
1420 /* Validate signature of open file.
1421 */
1422 if (0 != sh_gpg_check_sign (0, fd, 2))
1423 {
1424 retval = 1; exitval = EXIT_FAILURE;
1425 goto unlock_and_return;
1426 }
1427 sl_rewind (fd);
1428#endif
1429
1430 line = SH_ALLOC(MAX_PATH_STORE+2);
1431
1432 /* fast forward to start of data
1433 */
1434 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, file_path('D', 'R'));
1435
1436 for (i = 0; i < TABSIZE; ++i)
1437 tab[i] = NULL;
1438
1439 while (1)
1440 {
1441 if (sig_termfast == 1) /* SIGTERM */
1442 {
1443 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1444 --sig_raised; --sig_urgent;
1445 retval = 1; exitval = EXIT_SUCCESS;
1446 SH_FREE(line);
1447 line = NULL;
1448 goto unlock_and_return;
1449 }
1450
1451 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
1452 if (p != NULL)
1453 {
1454 hashinsert (p);
1455 ++count;
1456 }
1457 else
1458 break;
1459 }
1460
1461 /* Initialization completed.
1462 */
1463 IsInit = 1;
1464
1465 if (line != NULL)
1466 SH_FREE(line);
1467
1468 /* Always keep db in memory, so we have no open file
1469 */
1470 sl_close (fd);
1471 sh_hash_getline_end();
1472 fd = -1;
1473
1474 unlock_and_return:
1475 ; /* 'label at end of compound statement */
1476 SH_MUTEX_UNLOCK(mutex_hash);
1477 if (retval == 0)
1478 {
1479 SL_RET0(_("sh_hash_init"));
1480 }
1481 aud_exit (FIL__, __LINE__, exitval);
1482}
1483
1484/*****************************************************************
1485 *
1486 * delete hash array
1487 *
1488 *****************************************************************/
1489void sh_hash_hashdelete ()
1490{
1491 int i;
1492
1493 SL_ENTER(_("sh_hash_hashdelete"));
1494
1495 /* need deadlock detection here if called from exit handler
1496 */
1497 SH_MUTEX_TRYLOCK(mutex_hash);
1498
1499 if (IsInit == 0)
1500 goto unlock_and_exit;
1501
1502 for (i = 0; i < TABSIZE; ++i)
1503 if (tab[i] != NULL)
1504 {
1505 hash_kill (tab[i]);
1506 tab[i] = NULL;
1507 }
1508 IsInit = 0;
1509
1510 unlock_and_exit:
1511 ; /* 'label at end of compound statement */
1512 SH_MUTEX_TRYLOCK_UNLOCK(mutex_hash);
1513
1514 SL_RET0(_("sh_hash_hashdelete"));
1515}
1516
1517/******************************************************************
1518 *
1519 * Insert a file into the database.
1520 *
1521 ******************************************************************/
1522static int pushdata_isfirst = 1;
1523static SL_TICKET pushdata_fd = -1;
1524
1525static int pushdata_stdout = S_FALSE;
1526
1527static char * sh_db_version_string = NULL;
1528
1529int sh_hash_pushdata_stdout (const char * str)
1530{
1531 if (!str)
1532 { pushdata_stdout = S_TRUE; return 0; }
1533 return -1;
1534}
1535
1536int sh_hash_version_string(const char * str)
1537{
1538 if (str)
1539 {
1540 if (sh_db_version_string != NULL) {
1541 SH_FREE(sh_db_version_string);
1542 }
1543 if (0 == sl_strncmp(str, _("NULL"), 4))
1544 {
1545 sh_db_version_string = NULL;
1546 return 0;
1547 }
1548 sh_db_version_string = sh_util_strdup(str);
1549 return 0;
1550 }
1551 return -1;
1552}
1553
1554static int sh_loosedircheck = S_FALSE;
1555
1556int sh_hash_loosedircheck(const char * str)
1557{
1558 return sh_util_flagval(str, &sh_loosedircheck);
1559}
1560
1561
1562static void sh_hash_pushdata_int (file_type * buf, char * fileHash)
1563{
1564 static long p_count = 0;
1565
1566 int status = 0;
1567
1568 char * tmp;
1569 size_t tmp_len = 0;
1570 size_t old_len = 0;
1571 size_t path_len = 0;
1572
1573 sh_filestore_t p;
1574
1575 struct stat sbuf;
1576
1577 char * fullpath = NULL;
1578 char * linkpath = NULL;
1579 char * attr_string = NULL;
1580
1581 char * line = NULL;
1582
1583 char timestring[81];
1584
1585#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
1586 int i;
1587#endif
1588
1589 SL_ENTER(_("sh_hash_pushdata_int"));
1590
1591 fullpath = SH_ALLOC(MAX_PATH_STORE+1);
1592 linkpath = SH_ALLOC(MAX_PATH_STORE+1);
1593
1594 linkpath[0] = '-';
1595 linkpath[1] = '\0';
1596 fullpath[0] = '-';
1597 fullpath[1] = '\0';
1598
1599 if (!buf) {
1600 memset(&p, '\0', sizeof(sh_filestore_t));
1601 }
1602
1603 if ((pushdata_stdout == S_TRUE) && (sh.flag.update == S_TRUE))
1604 {
1605 dlog(1, FIL__, __LINE__,
1606 _("You cannot write the database to stdout when you use update rather than init.\n"));
1607 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1608 _("Writing database to stdout with update"),
1609 sh.prg_name,
1610 _("sh_hash_pushdata_int"));
1611 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1612 }
1613
1614 if ((pushdata_stdout == S_TRUE) && (sl_is_suid()))
1615 {
1616 dlog(1, FIL__, __LINE__,
1617 _("You cannot write the database to stdout when running with suid privileges.\n"));
1618 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1619 _("Writing database to stdout when suid"),
1620 sh.prg_name,
1621 _("sh_hash_pushdata_int"));
1622 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1623 }
1624
1625
1626 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) &&
1627 ( (NULL == file_path('D', 'W')) ||
1628 (0 == sl_strcmp(file_path('D', 'W'), _("REQ_FROM_SERVER"))) ))
1629 {
1630 dlog(1, FIL__, __LINE__,
1631 _("You need to configure a local path for initializing the database\nlike ./configure --with-data-file=REQ_FROM_SERVER/some/local/path\n"));
1632 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1633 _("No local path for database specified"),
1634 sh.prg_name,
1635 _("sh_hash_pushdata_int"));
1636 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1637 }
1638
1639
1640 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE))
1641 {
1642 /* Warn that file already exists; file_path != NULL here because
1643 * checked above
1644 */
1645 if (0 == retry_lstat(FIL__, __LINE__, file_path('D', 'W'), &sbuf))
1646 {
1647 if (sh.flag.update == S_FALSE)
1648 {
1649 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_FI_DBEX,
1650 file_path('D', 'W'));
1651 }
1652 }
1653 }
1654
1655
1656 if (sh.flag.update == S_FALSE)
1657 {
1658 if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
1659 {
1660 if ( SL_ISERROR(pushdata_fd = sl_open_write(FIL__, __LINE__,
1661 file_path('D', 'W'),
1662 SL_YESPRIV)))
1663 {
1664 SH_FREE(fullpath);
1665 SH_FREE(linkpath);
1666 sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
1667 geteuid(), file_path('D', 'W'));
1668 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1669 }
1670
1671 if (SL_ISERROR(status = sl_lock (pushdata_fd)))
1672 {
1673 SH_FREE(fullpath);
1674 SH_FREE(linkpath);
1675 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1676 _("Failed to lock baseline database"), _("sh_hash_pushdata_int"),
1677 file_path('D', 'W'));
1678 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1679 }
1680
1681 if ( SL_ISERROR(status = sl_forward(pushdata_fd)))
1682 {
1683 SH_FREE(fullpath);
1684 SH_FREE(linkpath);
1685 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1686 _("Failed to seek to end of baseline database"),
1687 _("sh_hash_pushdata_int"),
1688 file_path('D', 'W'));
1689 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1690 }
1691 }
1692 }
1693 else /* update == TRUE */
1694 {
1695 if (pushdata_isfirst == 1)
1696 {
1697 TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")))
1698 if ( SL_ISERROR(pushdata_fd = sl_open_rdwr(FIL__, __LINE__,
1699 file_path('D', 'W'),
1700 SL_YESPRIV))){
1701 SH_FREE(fullpath);
1702 SH_FREE(linkpath);
1703 sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
1704 geteuid(), file_path('D', 'W'));
1705 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1706 }
1707
1708 if (SL_ISERROR(status = sl_lock (pushdata_fd)))
1709 {
1710 SH_FREE(fullpath);
1711 SH_FREE(linkpath);
1712 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1713 _("Failed to lock baseline database"), _("sh_hash_pushdata_int"),
1714 file_path('D', 'W'));
1715 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1716 }
1717
1718 line = SH_ALLOC(MAX_PATH_STORE+1);
1719 if (SL_ISERROR(sh_hash_setdataent_old (pushdata_fd, line,
1720 MAX_PATH_STORE,
1721 file_path('D', 'W'))))
1722 {
1723 SH_FREE(fullpath);
1724 SH_FREE(linkpath);
1725 SH_FREE(line);
1726 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1727 }
1728 SH_FREE(line);
1729 }
1730 }
1731
1732 if (buf != NULL && buf->fullpath != NULL) {
1733
1734 old_len = sl_strlen(buf->fullpath);
1735#if defined(SH_STEALTH)
1736 sh_do_encode(buf->fullpath, old_len);
1737#endif
1738 tmp = quote_string(buf->fullpath, old_len);
1739 tmp_len = sl_strlen(tmp);
1740#if defined(SH_STEALTH)
1741 sh_do_decode(buf->fullpath, old_len);
1742#endif
1743
1744 if (tmp && tmp_len <= MAX_PATH_STORE)
1745 {
1746 sl_strlcpy(fullpath, buf->fullpath, MAX_PATH_STORE+1);
1747 }
1748 else
1749 {
1750 char hashbuf[KEYBUF_SIZE];
1751
1752 sl_strlcpy(fullpath,
1753 sh_tiger_hash (buf->fullpath,
1754 TIGER_DATA, old_len,
1755 hashbuf, sizeof(hashbuf)),
1756 KEY_LEN+1);
1757 }
1758 if (tmp) SH_FREE(tmp);
1759 }
1760
1761 path_len = sl_strlen(fullpath);
1762#if defined(SH_STEALTH)
1763 sh_do_encode(fullpath, path_len);
1764#endif
1765
1766 tmp = quote_string(fullpath, path_len);
1767 if (tmp) {
1768 sl_strlcpy(fullpath, tmp, MAX_PATH_STORE+1);
1769 SH_FREE(tmp);
1770 }
1771
1772 if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL)
1773 {
1774
1775 old_len = sl_strlen(buf->link_path);
1776#if defined(SH_STEALTH)
1777 if (buf->c_mode[0] == 'l')
1778 sh_do_encode(buf->link_path, old_len);
1779#endif
1780 tmp = quote_string(buf->link_path, old_len);
1781 tmp_len = sl_strlen(tmp);
1782#if defined(SH_STEALTH)
1783 if (buf->c_mode[0] == 'l')
1784 sh_do_decode(buf->link_path, old_len);
1785#endif
1786
1787 if (tmp && tmp_len <= MAX_PATH_STORE)
1788 {
1789 sl_strlcpy(linkpath, buf->link_path, MAX_PATH_STORE+1);
1790 }
1791 else
1792 {
1793 char hashbuf[KEYBUF_SIZE];
1794 sl_strlcpy(linkpath,
1795 sh_tiger_hash (buf->link_path,
1796 TIGER_DATA, old_len,
1797 hashbuf, sizeof(hashbuf)),
1798 KEY_LEN+1);
1799 }
1800 if (tmp) SH_FREE(tmp);
1801
1802 path_len = sl_strlen(linkpath);
1803#if defined(SH_STEALTH)
1804 if (buf->c_mode[0] == 'l')
1805 sh_do_encode(linkpath, path_len);
1806#endif
1807 tmp = quote_string(linkpath, path_len);
1808 if (tmp)
1809 {
1810 sl_strlcpy(linkpath, tmp, MAX_PATH_STORE+1);
1811 SH_FREE(tmp);
1812 }
1813 }
1814
1815 if (buf != NULL && buf->attr_string != NULL)
1816 {
1817 old_len = sl_strlen(buf->attr_string);
1818#if defined(SH_STEALTH)
1819 sh_do_encode(buf->attr_string, old_len);
1820#endif
1821 tmp = quote_string(buf->attr_string, old_len);
1822 if (tmp)
1823 {
1824 attr_string = tmp;
1825 tmp = NULL;
1826 }
1827#if defined(SH_STEALTH)
1828 sh_do_decode(buf->attr_string, old_len);
1829#endif
1830 }
1831
1832
1833 if (buf != NULL) {
1834 p.mark = REC_MAGIC;
1835 if (attr_string)
1836 p.mark |= REC_FLAGS_ATTR;
1837 sl_strlcpy(p.c_mode, buf->c_mode, CMODE_SIZE);
1838 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
1839 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
1840 if (fileHash) {
1841 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
1842 }
1843#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1844 sl_strlcpy(p.c_attributes, buf->c_attributes, ATTRBUF_SIZE);
1845#else
1846 for (i = 0; i < ATTRBUF_USED; ++i) p.c_attributes[i] = '-';
1847 p.c_attributes[ATTRBUF_USED] = '\0';
1848#endif
1849
1850#if defined(SH_STEALTH)
1851 sh_do_encode(p.c_mode, sl_strlen(p.c_mode));
1852 sh_do_encode(p.c_owner, sl_strlen(p.c_owner));
1853 sh_do_encode(p.c_group, sl_strlen(p.c_group));
1854 sh_do_encode(p.checksum, sl_strlen(p.checksum));
1855
1856 sh_do_encode(p.c_attributes, sl_strlen(p.c_attributes));
1857#endif
1858
1859#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1860 p.attributes = (UINT32) buf->attributes;
1861#else
1862 p.attributes = 0;
1863#endif
1864 p.linkmode = (UINT32) buf->linkmode;
1865 p.hardlinks = (UINT32) buf->hardlinks;
1866 p.dev = (UINT64) buf->dev;
1867 p.rdev = (UINT64) buf->rdev;
1868 p.mode = (UINT32) buf->mode;
1869 p.ino = (UINT32) buf->ino;
1870 p.size = (UINT64) buf->size;
1871 p.mtime = (UINT64) buf->mtime;
1872 p.atime = (UINT64) buf->atime;
1873 p.ctime = (UINT64) buf->ctime;
1874 p.owner = (UINT32) buf->owner;
1875 p.group = (UINT32) buf->group;
1876
1877 swap_32(&(p.mode));
1878 swap_32(&(p.linkmode));
1879 swap_64(&(p.dev));
1880 swap_64(&(p.rdev));
1881 swap_32(&(p.hardlinks));
1882 swap_32(&(p.ino));
1883 swap_64(&(p.size));
1884 swap_64(&(p.atime));
1885 swap_64(&(p.mtime));
1886 swap_64(&(p.ctime));
1887 swap_32(&(p.owner));
1888 swap_32(&(p.group));
1889 swap_32(&(p.attributes));
1890
1891#ifdef OLD_BUG
1892 swap_short(&(p.mark));
1893#else
1894 p.mark = *(swap_short(&(p.mark)));
1895#endif
1896 }
1897
1898 /* write the start marker
1899 */
1900 if (pushdata_isfirst == 1)
1901 {
1902 if (sh.flag.update == S_FALSE)
1903 {
1904 if (sh_db_version_string != NULL)
1905 {
1906 if (pushdata_stdout == S_FALSE)
1907 {
1908 sl_write (pushdata_fd, _("\n#Host "), 7);
1909 sl_write (pushdata_fd, sh.host.name,
1910 sl_strlen(sh.host.name));
1911 sl_write (pushdata_fd, _(" Version "), 9);
1912 sl_write (pushdata_fd, sh_db_version_string,
1913 sl_strlen(sh_db_version_string));
1914 sl_write (pushdata_fd, _(" Date "), 6);
1915 (void) sh_unix_time(0, timestring, sizeof(timestring));
1916 sl_write (pushdata_fd, timestring, strlen(timestring));
1917 sl_write (pushdata_fd, "\n", 1);
1918 } else {
1919 printf ("%s",_("\n#Host "));
1920 printf ("%s", sh.host.name);
1921 printf ("%s",_(" Version "));
1922 printf ("%s", sh_db_version_string);
1923 printf ("%s",_(" Date "));
1924 (void) sh_unix_time(0, timestring, sizeof(timestring));
1925 printf ("%s\n", timestring);
1926 }
1927 }
1928
1929 if (pushdata_stdout == S_FALSE)
1930 {
1931#if defined(SH_STEALTH)
1932 sl_write (pushdata_fd, "\n", 1);
1933 sl_write_line (pushdata_fd, N_("[SOF]"), 5);
1934#else
1935 sl_write_line (pushdata_fd, _("\n[SOF]"), 6);
1936#endif
1937 }
1938 else
1939 {
1940#if defined(SH_STEALTH)
1941 printf ("\n%s\n", N_("[SOF]"));
1942#else
1943 printf ("%s\n", _("\n[SOF]"));
1944#endif
1945 }
1946 }
1947 pushdata_isfirst = 0;
1948 }
1949
1950 if (pushdata_stdout == S_FALSE)
1951 {
1952 sl_write (pushdata_fd, &p, sizeof(sh_filestore_t));
1953 sl_write_line_fast (pushdata_fd, fullpath, sl_strlen(fullpath));
1954 sl_write_line_fast (pushdata_fd, linkpath, sl_strlen(linkpath));
1955 if (attr_string)
1956 sl_write_line_fast (pushdata_fd, attr_string, sl_strlen(attr_string));
1957 } else {
1958 if (fwrite (&p, sizeof(sh_filestore_t), 1, stdout))
1959 {
1960 printf ("%s\n", fullpath);
1961 printf ("%s\n", linkpath);
1962 if (attr_string)
1963 printf ("%s\n", attr_string);
1964 }
1965 else
1966 {
1967 perror(_("Error writing database"));
1968 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1969 }
1970 }
1971
1972 ++p_count;
1973
1974 if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
1975 {
1976 if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
1977 {
1978 sl_close (pushdata_fd);
1979 pushdata_fd = -1;
1980 }
1981 }
1982
1983 SH_FREE(fullpath);
1984 SH_FREE(linkpath);
1985 if (attr_string)
1986 SH_FREE(attr_string);
1987
1988 SL_RET0(_("sh_hash_pushdata_int"));
1989}
1990
1991SH_MUTEX_STATIC(mutex_writeout,PTHREAD_MUTEX_INITIALIZER);
1992
1993void sh_hash_pushdata (file_type * buf, char * fileHash)
1994{
1995 SH_MUTEX_LOCK(mutex_writeout);
1996 sh_hash_pushdata_int (buf, fileHash);
1997 SH_MUTEX_UNLOCK(mutex_writeout);
1998 return;
1999}
2000
2001
2002int sh_hash_writeout()
2003{
2004 sh_file_t * p;
2005 int i;
2006 file_type * f;
2007 char fileHash[KEY_LEN + 1];
2008
2009 SL_ENTER(_("sh_hash_writeout"));
2010
2011 if (S_TRUE == file_is_remote())
2012 {
2013 sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN,
2014 _("Baseline database is remote"), _("sh_hash_writeout"));
2015 SL_RETURN (1, _("sh_hash_writeout"));
2016 }
2017
2018 SH_MUTEX_LOCK(mutex_writeout);
2019 if (!SL_ISERROR(pushdata_fd))
2020 {
2021 sl_close(pushdata_fd);
2022 pushdata_fd = -1;
2023 }
2024 pushdata_isfirst = 1;
2025
2026
2027 SH_MUTEX_LOCK(mutex_hash);
2028 for (i = 0; i < TABSIZE; ++i)
2029 {
2030 for (p = tab[i]; p; p = p->next)
2031 {
2032 f = sh_hash_create_ft (p, fileHash);
2033 sh_hash_pushdata_int (f, fileHash);
2034 if (f->attr_string) SH_FREE(f->attr_string);
2035 if (f->link_path) SH_FREE(f->link_path);
2036 SH_FREE(f);
2037 }
2038 }
2039 SH_MUTEX_UNLOCK(mutex_hash);
2040
2041 if (!SL_ISERROR(pushdata_fd))
2042 {
2043 sl_close(pushdata_fd);
2044 pushdata_fd = -1;
2045 }
2046 pushdata_isfirst = 1;
2047 SH_MUTEX_UNLOCK(mutex_writeout);
2048
2049 SL_RETURN (0, _("sh_hash_writeout"));
2050}
2051
2052
2053/*********************************************************************
2054 *
2055 * Check whether a file is present in the database.
2056 *
2057 *********************************************************************/
2058static sh_file_t * sh_hash_have_it_int (const char * newname)
2059{
2060 sh_file_t * p;
2061 char hashbuf[KEYBUF_SIZE];
2062
2063 SL_ENTER(_("sh_hash_have_it_int"));
2064
2065 if (newname == NULL)
2066 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
2067
2068 if (sl_strlen(newname) <= MAX_PATH_STORE)
2069 p = hashsearch(newname);
2070 else
2071 p = hashsearch ( sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
2072 hashbuf, sizeof(hashbuf)) );
2073 if (p == NULL)
2074 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
2075
2076 SL_RETURN( (p), _("sh_hash_have_it_int"));
2077}
2078
2079int sh_hash_have_it (const char * newname)
2080{
2081 sh_file_t * p;
2082 int retval;
2083
2084 if (IsInit != 1)
2085 sh_hash_init();
2086
2087 SH_MUTEX_LOCK(mutex_hash);
2088
2089 retval = 0;
2090
2091 p = sh_hash_have_it_int (newname);
2092
2093 if (!p)
2094 retval = (-1);
2095 else if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) &&
2096 (p->modi_mask & MODI_CHK) != 0 &&
2097 (p->modi_mask & MODI_MOD) != 0)
2098 retval = 1;
2099 SH_MUTEX_UNLOCK(mutex_hash);
2100
2101 return retval;
2102}
2103
2104int sh_hash_get_it (const char * newname, file_type * tmpFile, char * fileHash)
2105{
2106 sh_file_t * p;
2107 int retval;
2108
2109 if (IsInit != 1)
2110 sh_hash_init();
2111
2112 tmpFile->link_path = NULL;
2113 tmpFile->attr_string = NULL;
2114
2115 SH_MUTEX_LOCK(mutex_hash);
2116
2117 retval = (-1);
2118
2119 p = sh_hash_have_it_int (newname);
2120 if (p)
2121 {
2122 sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
2123 if (p->linkpath)
2124 tmpFile->link_path = sh_util_strdup (p->linkpath);
2125 tmpFile->size = p->theFile.size;
2126 tmpFile->mtime = p->theFile.mtime;
2127 tmpFile->ctime = p->theFile.ctime;
2128 tmpFile->atime = p->theFile.atime;
2129
2130 if (NULL != fileHash)
2131 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
2132
2133 tmpFile->attr_string = NULL;
2134 retval = 0;
2135 }
2136 SH_MUTEX_UNLOCK(mutex_hash);
2137
2138 return retval;
2139}
2140
2141int sh_hash_getflags (char * filename)
2142{
2143 sh_file_t * p;
2144 int retval;
2145
2146 if (IsInit != 1)
2147 sh_hash_init();
2148
2149 SH_MUTEX_LOCK(mutex_hash);
2150 p = sh_hash_have_it_int (filename);
2151 if (p)
2152 retval = p->fflags;
2153 else
2154 retval = -1;
2155 SH_MUTEX_UNLOCK(mutex_hash);
2156 return retval;
2157}
2158
2159int sh_hash_setflags (char * filename, int flags)
2160{
2161 sh_file_t * p;
2162 int retval;
2163
2164 if (IsInit != 1)
2165 sh_hash_init();
2166
2167 SH_MUTEX_LOCK(mutex_hash);
2168 p = sh_hash_have_it_int (filename);
2169 if (p)
2170 {
2171 p->fflags = flags;
2172 retval = 0;
2173 }
2174 else
2175 retval = -1;
2176 SH_MUTEX_UNLOCK(mutex_hash);
2177 return retval;
2178}
2179
2180/* needs lock to be threadsafe
2181 */
2182void sh_hash_addflag (char * filename, int flag_to_set)
2183{
2184 sh_file_t * p;
2185
2186 if (IsInit != 1)
2187 sh_hash_init();
2188
2189 SH_MUTEX_LOCK(mutex_hash);
2190 p = sh_hash_have_it_int (filename);
2191 if (p)
2192 {
2193 p->fflags |= flag_to_set;
2194 }
2195 SH_MUTEX_UNLOCK(mutex_hash);
2196 return;
2197}
2198
2199/*****************************************************************
2200 *
2201 * Set a file's status to 'visited'. This is required for
2202 * files that should be ignored, and may be present in the
2203 * database, but not on disk.
2204 *
2205 *****************************************************************/
2206static int sh_hash_set_visited_int (char * newname, int flag)
2207{
2208 sh_file_t * p;
2209 char hashbuf[KEYBUF_SIZE];
2210 int retval;
2211
2212 SL_ENTER(_("sh_hash_set_visited_int"));
2213
2214 if (newname == NULL)
2215 SL_RETURN((-1), _("sh_hash_set_visited_int"));
2216
2217 if (IsInit != 1)
2218 sh_hash_init();
2219
2220 SH_MUTEX_LOCK(mutex_hash);
2221
2222 if (sl_strlen(newname) <= MAX_PATH_STORE)
2223 p = hashsearch(newname);
2224 else
2225 p = hashsearch (sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
2226 hashbuf, sizeof(hashbuf)));
2227
2228 if (p)
2229 {
2230 if (flag == SH_FFLAG_CHECKED)
2231 {
2232 CLEAR_SH_FFLAG_REPORTED(p->fflags);
2233 CLEAR_SH_FFLAG_VISITED(p->fflags);
2234 SET_SH_FFLAG_CHECKED(p->fflags);
2235 }
2236 else
2237 {
2238 SET_SH_FFLAG_VISITED(p->fflags);
2239 CLEAR_SH_FFLAG_CHECKED(p->fflags);
2240 if (flag == SH_FFLAG_REPORTED)
2241 SET_SH_FFLAG_REPORTED(p->fflags);
2242 else
2243 CLEAR_SH_FFLAG_REPORTED(p->fflags);
2244 }
2245 retval = 0;
2246 }
2247 else
2248 retval = -1;
2249
2250 SH_MUTEX_UNLOCK(mutex_hash);
2251 SL_RETURN((retval), _("sh_hash_set_visited_int"));
2252}
2253
2254
2255/* cause the record to be deleted without a 'missing' message
2256 */
2257int sh_hash_set_missing (char * newname)
2258{
2259 int i;
2260 SL_ENTER(_("sh_hash_set_missing"));
2261
2262 i = sh_hash_set_visited_int(newname, SH_FFLAG_CHECKED);
2263
2264 if (sh.flag.checkSum != SH_CHECK_INIT) {
2265 sh_hash_remove(newname);
2266 }
2267
2268 SL_RETURN(i, _("sh_hash_set_missing"));
2269}
2270
2271/* mark the file as visited and reported
2272 */
2273int sh_hash_set_visited (char * newname)
2274{
2275 int i;
2276 SL_ENTER(_("sh_hash_set_visited"));
2277 i = sh_hash_set_visited_int(newname, SH_FFLAG_REPORTED);
2278 SL_RETURN(i, _("sh_hash_set_visited"));
2279}
2280
2281/* mark the file as visited and NOT reported
2282 * used to avoid deletion of file from internal database
2283 */
2284int sh_hash_set_visited_true (char * newname)
2285{
2286 int i;
2287 SL_ENTER(_("sh_hash_set_visited_true"));
2288 i = sh_hash_set_visited_int(newname, 0);
2289 SL_RETURN(i, _("sh_hash_set_visited_true"));
2290}
2291
2292
2293/******************************************************************
2294 *
2295 * Data entry for arbitrary data into database
2296 *
2297 ******************************************************************/
2298
2299void sh_hash_push2db (const char * key, struct store2db * save)
2300{
2301 int i = 0;
2302 char * p;
2303 char i2h[2];
2304 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
2305
2306 int size = save->size;
2307 unsigned char * str = save->str;
2308
2309
2310 tmpFile->attr_string = NULL;
2311 tmpFile->link_path = NULL;
2312
2313 sl_strlcpy(tmpFile->fullpath, key, PATH_MAX);
2314 tmpFile->size = save->val0;
2315 tmpFile->mtime = save->val1;
2316 tmpFile->ctime = save->val2;
2317 tmpFile->atime = save->val3;
2318
2319 tmpFile->mode = 0;
2320 tmpFile->owner = 0;
2321 tmpFile->group = 0;
2322 sl_strlcpy(tmpFile->c_owner, _("root"), 5);
2323 sl_strlcpy(tmpFile->c_group, _("root"), 5);
2324
2325 if ((str != NULL) && (size < (PATH_MAX/2)-1))
2326 {
2327 tmpFile->c_mode[0] = 'l';
2328 tmpFile->c_mode[1] = 'r'; tmpFile->c_mode[2] = 'w';
2329 tmpFile->c_mode[3] = 'x'; tmpFile->c_mode[4] = 'r';
2330 tmpFile->c_mode[5] = 'w'; tmpFile->c_mode[6] = 'x';
2331 tmpFile->c_mode[7] = 'r'; tmpFile->c_mode[8] = 'w';
2332 tmpFile->c_mode[9] = 'x'; tmpFile->c_mode[10] = '\0';
2333 tmpFile->link_path = SH_ALLOC((size * 2) + 2);
2334 for (i = 0; i < size; ++i)
2335 {
2336 p = sh_util_charhex (str[i],i2h);
2337 tmpFile->link_path[2*i] = p[0];
2338 tmpFile->link_path[2*i+1] = p[1];
2339 tmpFile->link_path[2*i+2] = '\0';
2340 }
2341 }
2342 else
2343 {
2344 for (i = 0; i < 10; ++i)
2345 tmpFile->c_mode[i] = '-';
2346 tmpFile->c_mode[10] = '\0';
2347 tmpFile->link_path = sh_util_strdup("-");
2348 }
2349
2350 if (sh.flag.checkSum == SH_CHECK_INIT)
2351 sh_hash_pushdata (tmpFile,
2352 (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
2353 else
2354 sh_hash_pushdata_memory (tmpFile,
2355 (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
2356
2357 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
2358 SH_FREE(tmpFile);
2359 return;
2360}
2361
2362extern int sh_util_hextobinary (char * binary, char * hex, int bytes);
2363
2364char * sh_hash_db2pop (const char * key, struct store2db * save)
2365{
2366 size_t len;
2367 char * p;
2368 int i;
2369 char * retval = NULL;
2370 char fileHash[KEY_LEN+1];
2371 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
2372
2373 save->size = 0;
2374
2375 if (0 == sh_hash_get_it (key, tmpFile, fileHash))
2376 {
2377 save->val0 = tmpFile->size;
2378 save->val1 = tmpFile->mtime;
2379 save->val2 = tmpFile->ctime;
2380 save->val3 = tmpFile->atime;
2381
2382 sl_strlcpy(save->checksum, fileHash, KEY_LEN+1);
2383
2384 if (tmpFile->link_path && tmpFile->link_path[0] != '-')
2385 {
2386 len = strlen(tmpFile->link_path);
2387
2388 p = SH_ALLOC((len/2)+1);
2389 i = sh_util_hextobinary (p, tmpFile->link_path, len);
2390
2391 if (i == 0)
2392 {
2393 save->size = (len/2);
2394 p[save->size] = '\0';
2395 retval = p;
2396 }
2397 else
2398 {
2399 SH_FREE(p);
2400 save->size = 0;
2401 }
2402 }
2403 else
2404 {
2405 save->size = 0;
2406 }
2407 }
2408 else
2409 {
2410 save->size = -1;
2411 save->val0 = 0;
2412 save->val1 = 0;
2413 save->val2 = 0;
2414 save->val3 = 0;
2415 }
2416 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
2417 SH_FREE(tmpFile);
2418 return retval;
2419}
2420
2421
2422
2423
2424/******************************************************************
2425 *
2426 * Data entry in hash table
2427 *
2428 ******************************************************************/
2429sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
2430{
2431 sh_file_t * fp;
2432 sh_filestore_t p;
2433
2434 size_t len;
2435 char * fullpath;
2436 char * linkpath;
2437 char * attr_string = NULL;
2438 char hashbuf[KEYBUF_SIZE];
2439
2440 SL_ENTER(_("sh_hash_push_int"));
2441
2442 fp = SH_ALLOC(sizeof(sh_file_t));
2443
2444 p.mark = REC_MAGIC;
2445 if (buf->attr_string)
2446 p.mark |= REC_FLAGS_ATTR;
2447 sl_strlcpy(p.c_mode, buf->c_mode, 11);
2448 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
2449 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
2450 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
2451#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2452 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
2453#endif
2454
2455#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2456 p.attributes = (UINT32) buf->attributes;
2457#endif
2458 p.linkmode = (UINT32) buf->linkmode;
2459 p.hardlinks = (UINT32) buf->hardlinks;
2460 p.dev = (UINT64) buf->dev;
2461 p.rdev = (UINT64) buf->rdev;
2462 p.mode = (UINT32) buf->mode;
2463 p.ino = (UINT32) buf->ino;
2464 p.size = (UINT64) buf->size;
2465 p.mtime = (UINT64) buf->mtime;
2466 p.atime = (UINT64) buf->atime;
2467 p.ctime = (UINT64) buf->ctime;
2468 p.owner = (UINT32) buf->owner;
2469 p.group = (UINT32) buf->group;
2470
2471 memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
2472 fp->fflags = 0; /* init fflags */
2473 fp->modi_mask = 0L;
2474
2475 if (buf->attr_string)
2476 attr_string = sh_util_strdup(buf->attr_string);
2477 fp->attr_string = attr_string;
2478
2479 len = sl_strlen(buf->fullpath);
2480 if (len <= MAX_PATH_STORE)
2481 {
2482 fullpath = SH_ALLOC(len+1);
2483 sl_strlcpy(fullpath, buf->fullpath, len+1);
2484 }
2485 else
2486 {
2487 fullpath = SH_ALLOC(KEY_LEN + 1);
2488 sl_strlcpy(fullpath,
2489 sh_tiger_hash (buf->fullpath, TIGER_DATA, len,
2490 hashbuf, sizeof(hashbuf)),
2491 KEY_LEN+1);
2492 }
2493 fp->fullpath = fullpath;
2494
2495 if (buf->link_path)
2496 {
2497 len = sl_strlen(buf->link_path);
2498 if (len <= MAX_PATH_STORE)
2499 {
2500 linkpath = SH_ALLOC(len+1);
2501 sl_strlcpy(linkpath, buf->link_path, len+1);
2502 }
2503 else
2504 {
2505 linkpath = SH_ALLOC(KEY_LEN + 1);
2506 sl_strlcpy(linkpath,
2507 sh_tiger_hash (buf->link_path, TIGER_DATA, len,
2508 hashbuf, sizeof(hashbuf)),
2509 KEY_LEN+1);
2510 }
2511 fp->linkpath = linkpath;
2512 }
2513 else
2514 fp->linkpath = NULL;
2515
2516 SL_RETURN( fp, _("sh_hash_push_int"));
2517}
2518
2519#ifdef HAVE_INTTYPES_H
2520#include <inttypes.h>
2521#else
2522#ifdef HAVE_STDINT_H
2523#include <stdint.h>
2524#endif
2525#endif
2526
2527#ifndef PRIu64
2528#ifdef HAVE_LONG_32
2529#define PRIu64 "llu"
2530#else
2531#define PRIu64 "lu"
2532#endif
2533#endif
2534
2535char * sh_hash_size_format()
2536{
2537 static char form_rval[81];
2538
2539 SL_ENTER(_("sh_hash_size_format"));
2540
2541
2542#ifdef SH_USE_XML
2543 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2544 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
2545#else
2546 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2547 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
2548#endif
2549
2550 SL_RETURN( form_rval, _("sh_hash_size_format"));
2551}
2552
2553
2554#ifdef SH_USE_XML
2555static char * all_items (file_type * theFile, char * fileHash, int is_new)
2556{
2557 char timstr1c[32];
2558 char timstr1a[32];
2559 char timstr1m[32];
2560
2561 char * tmp_lnk;
2562 char * format;
2563
2564 char * tmp = SH_ALLOC(SH_MSG_BUF);
2565 char * msg = SH_ALLOC(SH_MSG_BUF);
2566
2567 tmp[0] = '\0';
2568 msg[0] = '\0';
2569
2570
2571#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2572 if (is_new)
2573 format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" ");
2574 else
2575 format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" ");
2576 sl_snprintf(tmp, SH_MSG_BUF, format,
2577 theFile->c_mode,
2578 theFile->c_attributes,
2579 (long) theFile->mode,
2580 (long) theFile->attributes
2581 );
2582#else
2583 if (is_new)
2584 format = _("mode_new=\"%s\" imode_new=\"%ld\" ");
2585 else
2586 format = _("mode_old=\"%s\" imode_old=\"%ld\" ");
2587
2588 sl_snprintf(tmp, SH_MSG_BUF, format,
2589 theFile->c_mode,
2590 (long) theFile->mode
2591 );
2592#endif
2593 sl_strlcat(msg, tmp, SH_MSG_BUF);
2594
2595 if (is_new)
2596 format = _("hardlinks_new=\"%lu\" ");
2597 else
2598 format = _("hardlinks_old=\"%lu\" ");
2599 sl_snprintf(tmp, SH_MSG_BUF, format,
2600 (unsigned long) theFile->hardlinks);
2601 sl_strlcat(msg, tmp, SH_MSG_BUF);
2602
2603
2604 if (is_new)
2605 format = _("idevice_new=\"%lu\" ");
2606 else
2607 format = _("idevice_old=\"%lu\" ");
2608 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2609 sl_strlcat(msg, tmp, SH_MSG_BUF);
2610
2611
2612 if (is_new)
2613 format = _("inode_new=\"%lu\" ");
2614 else
2615 format = _("inode_old=\"%lu\" ");
2616 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2617 sl_strlcat(msg, tmp, SH_MSG_BUF);
2618
2619 /*
2620 * also report device for prelude
2621 */
2622#if defined(HAVE_LIBPRELUDE)
2623 if (is_new)
2624 format = _("dev_new=\"%lu,%lu\" ");
2625 else
2626 format = _("dev_old=\"%lu,%lu\" ");
2627 sl_snprintf(tmp, SH_MSG_BUF, format,
2628 (unsigned long) major(theFile->dev),
2629 (unsigned long) minor(theFile->dev));
2630 sl_strlcat(msg, tmp, SH_MSG_BUF);
2631#endif
2632
2633
2634 if (is_new)
2635 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
2636 else
2637 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
2638 sl_snprintf(tmp, SH_MSG_BUF, format,
2639 theFile->c_owner, (long) theFile->owner);
2640 sl_strlcat(msg, tmp, SH_MSG_BUF);
2641
2642
2643 if (is_new)
2644 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
2645 else
2646 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
2647 sl_snprintf(tmp, SH_MSG_BUF, format,
2648 theFile->c_group, (long) theFile->group);
2649 sl_strlcat(msg, tmp, SH_MSG_BUF);
2650
2651
2652 if (is_new)
2653 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2654 (UINT64) 0, (UINT64) theFile->size);
2655 else
2656 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2657 (UINT64) theFile->size, (UINT64) 0);
2658 sl_strlcat(msg, tmp, SH_MSG_BUF);
2659
2660
2661 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2662 if (is_new)
2663 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=\"%s\" "), timstr1c);
2664 else
2665 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" "), timstr1c);
2666 sl_strlcat(msg, tmp, SH_MSG_BUF);
2667
2668 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2669 if (is_new)
2670 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=\"%s\" "), timstr1a);
2671 else
2672 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" "), timstr1a);
2673 sl_strlcat(msg, tmp, SH_MSG_BUF);
2674
2675 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2676 if (is_new)
2677 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=\"%s\" "), timstr1m);
2678 else
2679 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" "), timstr1m);
2680 sl_strlcat(msg, tmp, SH_MSG_BUF);
2681
2682 if (is_new)
2683 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=\"%s\" "), fileHash);
2684 else
2685 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=\"%s\" "), fileHash);
2686 sl_strlcat(msg, tmp, SH_MSG_BUF);
2687
2688 if (theFile->c_mode[0] == 'l' ||
2689 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
2690 {
2691 tmp_lnk = sh_util_safe_name(theFile->link_path);
2692 if (tmp_lnk)
2693 {
2694 if (is_new)
2695 sl_snprintf(tmp, SH_MSG_BUF, _("link_new=\"%s\" "), tmp_lnk);
2696 else
2697 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" "), tmp_lnk);
2698 SH_FREE(tmp_lnk);
2699 sl_strlcat(msg, tmp, SH_MSG_BUF);
2700 }
2701 }
2702
2703 if (theFile->attr_string)
2704 {
2705 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2706 if (tmp_lnk)
2707 {
2708 if (is_new)
2709 sl_snprintf(tmp, SH_MSG_BUF, _("acl_new=\"%s\" "), tmp_lnk);
2710 else
2711 sl_snprintf(tmp, SH_MSG_BUF, _("acl_old=\"%s\" "), tmp_lnk);
2712 SH_FREE(tmp_lnk);
2713 sl_strlcat(msg, tmp, SH_MSG_BUF);
2714 }
2715 }
2716
2717
2718 SH_FREE(tmp);
2719 return (msg);
2720}
2721#else
2722static char * all_items (file_type * theFile, char * fileHash, int is_new)
2723{
2724 char timstr1c[32];
2725 char timstr1a[32];
2726 char timstr1m[32];
2727
2728 char * tmp_lnk;
2729 char * format;
2730
2731 char * tmp = SH_ALLOC(SH_MSG_BUF);
2732 char * msg = SH_ALLOC(SH_MSG_BUF);
2733
2734 tmp[0] = '\0';
2735 msg[0] = '\0';
2736
2737
2738#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2739 if (is_new)
2740 format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, ");
2741 else
2742 format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, ");
2743 sl_snprintf(tmp, SH_MSG_BUF, format,
2744 theFile->c_mode,
2745 theFile->c_attributes,
2746 (long) theFile->mode,
2747 (long) theFile->attributes
2748 );
2749#else
2750 if (is_new)
2751 format = _("mode_new=<%s>, imode_new=<%ld>, ");
2752 else
2753 format = _("mode_old=<%s>, imode_old=<%ld>, ");
2754
2755 sl_snprintf(tmp, SH_MSG_BUF, format,
2756 theFile->c_mode,
2757 (long) theFile->mode
2758 );
2759#endif
2760 sl_strlcat(msg, tmp, SH_MSG_BUF);
2761
2762 if (is_new)
2763 format = _("hardlinks_new=<%lu>, ");
2764 else
2765 format = _("hardlinks_old=<%lu>, ");
2766 sl_snprintf(tmp, SH_MSG_BUF, format,
2767 (unsigned long) theFile->hardlinks);
2768 sl_strlcat(msg, tmp, SH_MSG_BUF);
2769
2770
2771 if (is_new)
2772 format = _("idevice_new=<%lu>, ");
2773 else
2774 format = _("idevice_old=<%lu>, ");
2775 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2776 sl_strlcat(msg, tmp, SH_MSG_BUF);
2777
2778
2779 if (is_new)
2780 format = _("inode_new=<%lu>, ");
2781 else
2782 format = _("inode_old=<%lu>, ");
2783 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2784 sl_strlcat(msg, tmp, SH_MSG_BUF);
2785
2786
2787 /*
2788 * also report device for prelude
2789 */
2790#if defined(HAVE_LIBPRELUDE)
2791 if (is_new)
2792 format = _("dev_new=<%lu,%lu>, ");
2793 else
2794 format = _("dev_old=<%lu,%lu>, ");
2795 sl_snprintf(tmp, SH_MSG_BUF, format,
2796 (unsigned long) major(theFile->dev),
2797 (unsigned long) minor(theFile->dev));
2798 sl_strlcat(msg, tmp, SH_MSG_BUF);
2799#endif
2800
2801 if (is_new)
2802 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
2803 else
2804 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
2805 sl_snprintf(tmp, SH_MSG_BUF, format,
2806 theFile->c_owner, (long) theFile->owner);
2807 sl_strlcat(msg, tmp, SH_MSG_BUF);
2808
2809
2810 if (is_new)
2811 format = _("group_new=<%s>, igroup_new=<%ld>, ");
2812 else
2813 format = _("group_old=<%s>, igroup_old=<%ld>, ");
2814 sl_snprintf(tmp, SH_MSG_BUF, format,
2815 theFile->c_group, (long) theFile->group);
2816 sl_strlcat(msg, tmp, SH_MSG_BUF);
2817
2818
2819 if (is_new)
2820 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2821 (UINT64) 0, (UINT64) theFile->size);
2822 else
2823 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2824 (UINT64) theFile->size, (UINT64) 0);
2825 sl_strlcat(msg, tmp, SH_MSG_BUF);
2826
2827
2828 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2829 if (is_new)
2830 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=<%s>, "), timstr1c);
2831 else
2832 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, "), timstr1c);
2833 sl_strlcat(msg, tmp, SH_MSG_BUF);
2834
2835 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2836 if (is_new)
2837 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=<%s>, "), timstr1a);
2838 else
2839 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, "), timstr1a);
2840 sl_strlcat(msg, tmp, SH_MSG_BUF);
2841
2842 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2843 if (is_new)
2844 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=<%s>, "), timstr1m);
2845 else
2846 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, "), timstr1m);
2847 sl_strlcat(msg, tmp, SH_MSG_BUF);
2848
2849 if (is_new)
2850 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=<%s>"), fileHash);
2851 else
2852 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=<%s>"), fileHash);
2853 sl_strlcat(msg, tmp, SH_MSG_BUF);
2854
2855 if (theFile->c_mode[0] == 'l' ||
2856 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
2857 {
2858 tmp_lnk = sh_util_safe_name(theFile->link_path);
2859 if (tmp_lnk)
2860 {
2861 if (is_new)
2862 sl_snprintf(tmp, SH_MSG_BUF, _(", link_new=<%s> "), tmp_lnk);
2863 else
2864 sl_snprintf(tmp, SH_MSG_BUF, _(", link_old=<%s> "), tmp_lnk);
2865 SH_FREE(tmp_lnk);
2866 sl_strlcat(msg, tmp, SH_MSG_BUF);
2867 }
2868 }
2869
2870 if (theFile->attr_string)
2871 {
2872 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2873 if (tmp_lnk)
2874 {
2875 if (is_new)
2876 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_new=<%s> "), tmp_lnk);
2877 else
2878 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_old=<%s> "), tmp_lnk);
2879 SH_FREE(tmp_lnk);
2880 sl_strlcat(msg, tmp, SH_MSG_BUF);
2881 }
2882 }
2883
2884 SH_FREE(tmp);
2885 return (msg);
2886}
2887#endif
2888
2889void sh_hash_pushdata_memory (file_type * theFile, char * fileHash)
2890{
2891 sh_file_t * p;
2892
2893 SL_ENTER(_("sh_hash_pushdata_memory"));
2894
2895 p = sh_hash_push_int(theFile, fileHash);
2896 if (p)
2897 {
2898 SH_MUTEX_LOCK(mutex_hash);
2899 hashinsert (p);
2900 p->modi_mask = theFile->check_mask;
2901 SH_MUTEX_UNLOCK(mutex_hash);
2902 }
2903
2904 SL_RET0(_("sh_hash_pushdata_memory"));
2905}
2906
2907
2908/*****************************************************************
2909 *
2910 * Compare a file with the database status.
2911 *
2912 *****************************************************************/
2913int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
2914 char * policy_override, int severity_override)
2915{
2916 char * msg;
2917 sh_file_t * p;
2918 char * tmp;
2919 char * tmp_path;
2920 char * tmp_lnk;
2921 char * tmp_lnk_old;
2922
2923 char * str;
2924
2925 char timstr1c[32];
2926 char timstr2c[32];
2927 char timstr1a[32];
2928 char timstr2a[32];
2929 char timstr1m[32];
2930 char timstr2m[32];
2931 char linkHash[KEY_LEN+1];
2932 char * linkComp;
2933 int maxcomp;
2934
2935 char change_code[16];
2936 int i;
2937
2938 unsigned long modi_mask;
2939
2940 char log_policy[32];
2941 volatile int log_severity;
2942 char hashbuf[KEYBUF_SIZE];
2943
2944 int retval;
2945
2946 SL_ENTER(_("sh_hash_compdata"));
2947
2948 if (IsInit != 1) sh_hash_init();
2949
2950 if (severity_override < 0)
2951 log_severity = ShDFLevel[class];
2952 else
2953 log_severity = severity_override;
2954
2955 if (policy_override != NULL)
2956 sl_strlcpy (log_policy, policy_override, 32);
2957
2958 /* -------- find the entry for the file ---------------- */
2959
2960 SH_MUTEX_LOCK(mutex_hash);
2961
2962 modi_mask = 0;
2963 retval = 0;
2964
2965 if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE)
2966 p = hashsearch(theFile->fullpath);
2967 else
2968 p = hashsearch( sh_tiger_hash(theFile->fullpath,
2969 TIGER_DATA,
2970 sl_strlen(theFile->fullpath),
2971 hashbuf, sizeof(hashbuf))
2972 );
2973
2974
2975 /* --------- Not found in database. ------------
2976 */
2977
2978 if (p == NULL)
2979 {
2980 if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
2981 {
2982 tmp = sh_util_safe_name(theFile->fullpath);
2983
2984 str = all_items (theFile, fileHash, 1);
2985 sh_error_handle (log_severity, FIL__, __LINE__, 0,
2986 MSG_FI_ADD2,
2987 tmp, str);
2988 SH_FREE(str);
2989
2990 SH_FREE(tmp);
2991 }
2992
2993 if (sh.flag.reportonce == S_TRUE)
2994 SET_SH_FFLAG_REPORTED(theFile->file_reported);
2995
2996 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2997 {
2998 p = sh_hash_push_int(theFile, fileHash);
2999 if (p)
3000 {
3001 hashinsert (p);
3002 p->modi_mask = theFile->check_mask;
3003 }
3004 }
3005
3006 else if (S_TRUE == sh.flag.update)
3007 {
3008 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
3009 {
3010 p = sh_hash_push_int(theFile, fileHash);
3011 if (p)
3012 {
3013 hashinsert (p);
3014 p->modi_mask = theFile->check_mask;
3015 }
3016 }
3017 else
3018 {
3019 retval = 1;
3020 goto unlock_and_return;
3021 }
3022 }
3023
3024 goto unlock_and_return;
3025 }
3026
3027 p->modi_mask = theFile->check_mask;
3028
3029 /* initialize change_code */
3030 for (i = 0; i < 15; ++i)
3031 change_code[i] = '-';
3032 change_code[15] = '\0';
3033
3034 TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"),
3035 theFile->fullpath, fileHash, p->theFile.checksum));
3036
3037 if ( (fileHash != NULL) && (p->theFile.checksum != NULL) &&
3038 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
3039 (theFile->check_mask & MODI_CHK) != 0)
3040 {
3041 if ((theFile->check_mask & MODI_SGROW) == 0)
3042 {
3043 modi_mask |= MODI_CHK;
3044 change_code[0] = 'C';
3045 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
3046 }
3047 else
3048 {
3049 if (0 != strncmp (&fileHash[KEY_LEN + 1],
3050 p->theFile.checksum, KEY_LEN))
3051 {
3052 modi_mask |= MODI_CHK;
3053 change_code[0] = 'C';
3054 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
3055 }
3056 else
3057 {
3058 p->theFile.size = theFile->size;
3059 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3060 }
3061 }
3062 }
3063
3064 if (p->theFile.c_mode[0] == 'l')
3065 {
3066 if (!(theFile->link_path) &&
3067 (theFile->check_mask & MODI_LNK) != 0)
3068 {
3069 linkComp = NULL;
3070 modi_mask |= MODI_LNK;
3071 change_code[1] = 'L';
3072 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
3073 }
3074 else
3075 {
3076 if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE)
3077 {
3078 sl_strlcpy(linkHash,
3079 sh_tiger_hash(theFile->link_path,
3080 TIGER_DATA,
3081 sl_strlen(theFile->link_path),
3082 hashbuf, sizeof(hashbuf)),
3083 MAX_PATH_STORE+1);
3084 linkComp = linkHash;
3085 maxcomp = KEY_LEN;
3086 }
3087 else
3088 {
3089 linkComp = theFile->link_path;
3090 maxcomp = MAX_PATH_STORE;
3091 }
3092
3093 if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 &&
3094 (theFile->check_mask & MODI_LNK) != 0)
3095 {
3096 modi_mask |= MODI_LNK;
3097 change_code[1] = 'L';
3098 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
3099 }
3100 }
3101 }
3102
3103 if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b')
3104 {
3105 if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) ||
3106 minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
3107 (theFile->check_mask & MODI_RDEV) != 0)
3108 {
3109 modi_mask |= MODI_RDEV;
3110 change_code[2] = 'D';
3111 TPT ((0, FIL__, __LINE__, _("mod=<rdev>")));
3112 }
3113 }
3114
3115 /* cast to UINT32 in case ino_t is not 32bit
3116 */
3117 if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino &&
3118 (theFile->check_mask & MODI_INO) != 0)
3119 {
3120 modi_mask |= MODI_INO;
3121 change_code[3] = 'I';
3122 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
3123 }
3124
3125 if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
3126 (theFile->check_mask & MODI_HLN) != 0)
3127 {
3128 modi_mask |= MODI_HLN;
3129 change_code[4] = 'H';
3130 TPT ((0, FIL__, __LINE__, _("mod=<hardlink>")));
3131 }
3132
3133
3134 if ( ( (theFile->mode != p->theFile.mode)
3135#if defined(USE_ACL) || defined(USE_XATTR)
3136 || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
3137 (
3138 (theFile->attr_string == NULL && p->attr_string != NULL) ||
3139 (theFile->attr_string != NULL && p->attr_string == NULL) ||
3140 (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
3141 )
3142 )
3143#endif
3144#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3145 || (theFile->attributes != p->theFile.attributes)
3146#endif
3147 )
3148 && (theFile->check_mask & MODI_MOD) != 0)
3149 {
3150 modi_mask |= MODI_MOD;
3151 change_code[5] = 'M';
3152 TPT ((0, FIL__, __LINE__, _("mod=<mode>")));
3153 /*
3154 * report link path if switch link/no link
3155 */
3156 if ((theFile->check_mask & MODI_LNK) != 0 &&
3157 (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
3158 (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
3159 {
3160 modi_mask |= MODI_LNK;
3161 change_code[1] = 'L';
3162 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
3163 }
3164 }
3165
3166 if ( theFile->owner != (uid_t) p->theFile.owner &&
3167 (theFile->check_mask & MODI_USR) != 0)
3168 {
3169 modi_mask |= MODI_USR;
3170 change_code[6] = 'U';
3171 TPT ((0, FIL__, __LINE__, _("mod=<user>")));
3172 }
3173
3174 if ( theFile->group != (gid_t) p->theFile.group &&
3175 (theFile->check_mask & MODI_GRP) != 0)
3176 {
3177 modi_mask |= MODI_GRP;
3178 change_code[7] = 'G';
3179 TPT ((0, FIL__, __LINE__, _("mod=<group>")));
3180 }
3181
3182
3183 if ( theFile->mtime != (time_t) p->theFile.mtime &&
3184 (theFile->check_mask & MODI_MTM) != 0)
3185 {
3186 modi_mask |= MODI_MTM;
3187 change_code[8] = 'T';
3188 TPT ((0, FIL__, __LINE__, _("mod=<mtime>")));
3189 }
3190
3191 if ( (theFile->check_mask & MODI_ATM) != 0 &&
3192 theFile->atime != (time_t) p->theFile.atime)
3193 {
3194 modi_mask |= MODI_ATM;
3195 change_code[8] = 'T';
3196 TPT ((0, FIL__, __LINE__, _("mod=<atime>")));
3197 }
3198
3199
3200 /* Resetting the access time will set a new ctime. Thus, either we ignore
3201 * the access time or the ctime for NOIGNORE
3202 */
3203 if ( theFile->ctime != (time_t) p->theFile.ctime &&
3204 (theFile->check_mask & MODI_CTM) != 0)
3205 {
3206 modi_mask |= MODI_CTM;
3207 change_code[8] = 'T';
3208 TPT ((0, FIL__, __LINE__, _("mod=<ctime>")));
3209 }
3210
3211 if ( theFile->size != (off_t) p->theFile.size &&
3212 (theFile->check_mask & MODI_SIZ) != 0)
3213 {
3214 if ((theFile->check_mask & MODI_SGROW) == 0 ||
3215 theFile->size < (off_t) p->theFile.size)
3216 {
3217 modi_mask |= MODI_SIZ;
3218 change_code[9] = 'S';
3219 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
3220 }
3221 }
3222 change_code[10] = '\0';
3223
3224 /* --- Directories special case ---
3225 */
3226 if (p->theFile.c_mode[0] == 'd' &&
3227 0 == (modi_mask & ~(MODI_SIZ|MODI_ATM|MODI_CTM|MODI_MTM)) &&
3228 sh_loosedircheck == S_TRUE)
3229 {
3230 modi_mask = 0;
3231 }
3232
3233 /* --- Report full details. ---
3234 */
3235 if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
3236 {
3237 if ((theFile->check_mask & MODI_ATM) == 0)
3238 modi_mask = MASK_READONLY_;
3239 else
3240 modi_mask = MASK_NOIGNORE_;
3241 }
3242
3243 /* --- Report on modified files. ---
3244 */
3245 if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
3246 {
3247 tmp = SH_ALLOC(SH_MSG_BUF);
3248 msg = SH_ALLOC(SH_MSG_BUF);
3249 msg[0] = '\0';
3250
3251 if ( ((modi_mask & MODI_MOD) != 0)
3252#if defined(HAVE_LIBPRELUDE)
3253 || ((modi_mask & MODI_USR) != 0)
3254 || ((modi_mask & MODI_GRP) != 0)
3255#endif
3256 )
3257 {
3258#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3259 sl_snprintf(tmp, SH_MSG_BUF,
3260#ifdef SH_USE_XML
3261 _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "),
3262#else
3263 _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "),
3264#endif
3265 p->theFile.c_mode, theFile->c_mode,
3266 p->theFile.c_attributes, theFile->c_attributes
3267#ifdef SH_USE_XML
3268 , (long) p->theFile.mode, (long) theFile->mode,
3269 (long) p->theFile.attributes,
3270 (long) theFile->attributes
3271#endif
3272 );
3273#else
3274#ifdef SH_USE_XML
3275 sl_snprintf(tmp, SH_MSG_BUF,
3276 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
3277 p->theFile.c_mode, theFile->c_mode,
3278 (long) p->theFile.mode, (long) theFile->mode);
3279#else
3280 sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=<%s>, mode_new=<%s>, "),
3281 p->theFile.c_mode, theFile->c_mode);
3282#endif
3283#endif
3284 sl_strlcat(msg, tmp, SH_MSG_BUF);
3285
3286#if defined(USE_ACL) || defined(USE_XATTR)
3287 if (theFile->attr_string != NULL || p->attr_string != NULL)
3288 {
3289 sl_snprintf(tmp, SH_MSG_BUF,
3290#ifdef SH_USE_XML
3291 _("acl_old=\"%s\" acl_new=\"%s\" "),
3292#else
3293 _("acl_old=<%s>, acl_new=<%s>, "),
3294#endif
3295 (p->attr_string) ? p->attr_string : _("none"),
3296 (theFile->attr_string) ? theFile->attr_string : _("none"));
3297
3298 sl_strlcat(msg, tmp, SH_MSG_BUF);
3299 }
3300#endif
3301
3302#ifdef REPLACE_OLD
3303 if ((modi_mask & MODI_MOD) != 0)
3304 {
3305 /*
3306 * We postpone update if sh.flag.update == S_TRUE because
3307 * in interactive mode the user may not accept the change.
3308 */
3309 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3310 {
3311 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3312 p->theFile.mode = theFile->mode;
3313#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3314 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
3315 p->theFile.attributes = theFile->attributes;
3316#endif
3317#if defined(USE_ACL) || defined(USE_XATTR)
3318 if (p->attr_string == NULL && theFile->attr_string != NULL)
3319 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3320 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3321 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3322 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3323 {
3324 if (0 != strcmp(theFile->attr_string, p->attr_string))
3325 {
3326 SH_FREE(p->attr_string);
3327 p->attr_string = sh_util_strdup (theFile->attr_string);
3328 }
3329 }
3330#endif
3331 }
3332 }
3333#endif
3334 }
3335
3336 if ((modi_mask & MODI_HLN) != 0)
3337 {
3338 sl_snprintf(tmp, SH_MSG_BUF,
3339#ifdef SH_USE_XML
3340 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
3341#else
3342 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
3343#endif
3344 (unsigned long) p->theFile.hardlinks,
3345 (unsigned long) theFile->hardlinks);
3346 sl_strlcat(msg, tmp, SH_MSG_BUF);
3347#ifdef REPLACE_OLD
3348 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3349 p->theFile.hardlinks = theFile->hardlinks;
3350#endif
3351 }
3352
3353 if ((modi_mask & MODI_RDEV) != 0)
3354 {
3355 sl_snprintf(tmp, SH_MSG_BUF,
3356#ifdef SH_USE_XML
3357 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
3358#else
3359 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
3360#endif
3361 (unsigned long) major(p->theFile.rdev),
3362 (unsigned long) minor(p->theFile.rdev),
3363 (unsigned long) major(theFile->rdev),
3364 (unsigned long) minor(theFile->rdev)
3365#ifdef SH_USE_XML
3366 , (unsigned long) p->theFile.rdev,
3367 (unsigned long) theFile->rdev
3368#endif
3369 );
3370 sl_strlcat(msg, tmp, SH_MSG_BUF);
3371#ifdef REPLACE_OLD
3372 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3373 p->theFile.rdev = theFile->rdev;
3374#endif
3375 }
3376
3377 if ((modi_mask & MODI_INO) != 0)
3378 {
3379 sl_snprintf(tmp, SH_MSG_BUF,
3380#ifdef SH_USE_XML
3381 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
3382#else
3383 _("inode_old=<%lu>, inode_new=<%lu>, "),
3384#endif
3385 (unsigned long) p->theFile.ino,
3386 (unsigned long) theFile->ino);
3387 sl_strlcat(msg, tmp, SH_MSG_BUF);
3388#ifdef REPLACE_OLD
3389 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3390 {
3391 p->theFile.ino = theFile->ino;
3392 p->theFile.dev = theFile->dev;
3393 }
3394#endif
3395 }
3396
3397
3398 /*
3399 * also report device for prelude
3400 */
3401#if defined(HAVE_LIBPRELUDE)
3402 if ((modi_mask & MODI_INO) != 0)
3403 {
3404 sl_snprintf(tmp, SH_MSG_BUF,
3405#ifdef SH_USE_XML
3406 _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "),
3407#else
3408 _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "),
3409#endif
3410 (unsigned long) major(p->theFile.dev),
3411 (unsigned long) minor(p->theFile.dev),
3412 (unsigned long) major(theFile->dev),
3413 (unsigned long) minor(theFile->dev)
3414 );
3415 sl_strlcat(msg, tmp, SH_MSG_BUF);
3416#ifdef REPLACE_OLD
3417 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3418 p->theFile.dev = theFile->dev;
3419#endif
3420 }
3421#endif
3422
3423 if ( ((modi_mask & MODI_USR) != 0)
3424#if defined(HAVE_LIBPRELUDE)
3425 || ((modi_mask & MODI_MOD) != 0)
3426#endif
3427 )
3428 {
3429#ifdef SH_USE_XML
3430 sl_snprintf(tmp, SH_MSG_BUF,
3431 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
3432#else
3433 sl_snprintf(tmp, SH_MSG_BUF,
3434 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
3435#endif
3436 p->theFile.c_owner, theFile->c_owner,
3437 (long) p->theFile.owner, (long) theFile->owner
3438 );
3439 sl_strlcat(msg, tmp, SH_MSG_BUF);
3440#ifdef REPLACE_OLD
3441 if ((modi_mask & MODI_USR) != 0) {
3442 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3443 {
3444 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3445 p->theFile.owner = theFile->owner;
3446 }
3447 }
3448#endif
3449 }
3450
3451 if ( ((modi_mask & MODI_GRP) != 0)
3452#if defined(HAVE_LIBPRELUDE)
3453 || ((modi_mask & MODI_MOD) != 0)
3454#endif
3455 )
3456 {
3457#ifdef SH_USE_XML
3458 sl_snprintf(tmp, SH_MSG_BUF,
3459 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
3460 p->theFile.c_group, theFile->c_group,
3461 (long) p->theFile.group, (long) theFile->group);
3462#else
3463 sl_snprintf(tmp, SH_MSG_BUF,
3464 _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "),
3465 p->theFile.c_group, theFile->c_group,
3466 (long) p->theFile.group, (long) theFile->group);
3467#endif
3468
3469 sl_strlcat(msg, tmp, SH_MSG_BUF);
3470#ifdef REPLACE_OLD
3471 if ((modi_mask & MODI_GRP) != 0) {
3472 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3473 {
3474 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3475 p->theFile.group = theFile->group;
3476 }
3477 }
3478#endif
3479 }
3480
3481 if ((modi_mask & MODI_SIZ) != 0)
3482 {
3483 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
3484 (UINT64) p->theFile.size,
3485 (UINT64) theFile->size);
3486 sl_strlcat(msg, tmp, SH_MSG_BUF);
3487#ifdef REPLACE_OLD
3488 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3489 p->theFile.size = theFile->size;
3490#endif
3491 }
3492
3493 if ((modi_mask & MODI_CTM) != 0)
3494 {
3495 (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c));
3496 (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c));
3497#ifdef SH_USE_XML
3498 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
3499 timstr1c, timstr2c);
3500#else
3501 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, ctime_new=<%s>, "),
3502 timstr1c, timstr2c);
3503#endif
3504 sl_strlcat(msg, tmp, SH_MSG_BUF);
3505#ifdef REPLACE_OLD
3506 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3507 p->theFile.ctime = theFile->ctime;
3508#endif
3509 }
3510
3511 if ((modi_mask & MODI_ATM) != 0)
3512 {
3513 (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a));
3514 (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a));
3515#ifdef SH_USE_XML
3516 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" atime_new=\"%s\" "),
3517 timstr1a, timstr2a);
3518#else
3519 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, atime_new=<%s>, "),
3520 timstr1a, timstr2a);
3521#endif
3522 sl_strlcat(msg, tmp, SH_MSG_BUF);
3523#ifdef REPLACE_OLD
3524 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3525 p->theFile.atime = theFile->atime;
3526#endif
3527 }
3528
3529 if ((modi_mask & MODI_MTM) != 0)
3530 {
3531 (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m));
3532 (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m));
3533#ifdef SH_USE_XML
3534 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
3535 timstr1m, timstr2m);
3536#else
3537 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, mtime_new=<%s>, "),
3538 timstr1m, timstr2m);
3539#endif
3540 sl_strlcat(msg, tmp, SH_MSG_BUF);
3541#ifdef REPLACE_OLD
3542 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3543 p->theFile.mtime = theFile->mtime;
3544#endif
3545 }
3546
3547
3548 if ((modi_mask & MODI_CHK) != 0)
3549 {
3550 sl_snprintf(tmp, SH_MSG_BUF,
3551#ifdef SH_USE_XML
3552 _("chksum_old=\"%s\" chksum_new=\"%s\" "),
3553#else
3554 _("chksum_old=<%s>, chksum_new=<%s>, "),
3555#endif
3556 p->theFile.checksum, fileHash);
3557 sl_strlcat(msg, tmp, SH_MSG_BUF);
3558#ifdef REPLACE_OLD
3559 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3560 {
3561 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3562 if ((theFile->check_mask & MODI_SGROW) != 0)
3563 p->theFile.size = theFile->size;
3564 }
3565#endif
3566 /* FIXME is this correct? */
3567 if (theFile->c_mode[0] != 'l' && theFile->link_path &&
3568 strlen(theFile->link_path) > 2)
3569 modi_mask |= MODI_LNK;
3570 }
3571
3572
3573 if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */)
3574 {
3575 if (theFile->link_path)
3576 tmp_lnk = sh_util_safe_name(theFile->link_path);
3577 else
3578 tmp_lnk = sh_util_strdup("-");
3579 if (p->linkpath)
3580 tmp_lnk_old = sh_util_safe_name(p->linkpath);
3581 else
3582 tmp_lnk_old = sh_util_strdup("-");
3583#ifdef SH_USE_XML
3584 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" link_new=\"%s\" "),
3585 tmp_lnk_old, tmp_lnk);
3586#else
3587 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=<%s>, link_new=<%s>, "),
3588 tmp_lnk_old, tmp_lnk);
3589#endif
3590 SH_FREE(tmp_lnk);
3591 SH_FREE(tmp_lnk_old);
3592 sl_strlcat(msg, tmp, SH_MSG_BUF);
3593#ifdef REPLACE_OLD
3594 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3595 {
3596 if (p->linkpath != NULL && p->linkpath != notalink)
3597 SH_FREE(p->linkpath);
3598 if (!(theFile->link_path) ||
3599 (theFile->link_path[0] == '-' && theFile->link_path[1] == '\0'))
3600 p->linkpath = (char *)notalink;
3601 else
3602 p->linkpath = sh_util_strdup(theFile->link_path);
3603 }
3604#endif
3605 }
3606
3607 if (MODI_AUDIT_ENABLED(theFile->check_mask))
3608 {
3609 char result[256];
3610
3611 if (NULL != sh_audit_fetch (theFile->fullpath, theFile->mtime, result, sizeof(result)))
3612 {
3613#ifdef SH_USE_XML
3614 sl_strlcat(msg, _("obj=\""), SH_MSG_BUF);
3615#else
3616 sl_strlcat(msg, _("obj=<"), SH_MSG_BUF);
3617#endif
3618
3619 sl_strlcat(msg, result, SH_MSG_BUF);
3620
3621#ifdef SH_USE_XML
3622 sl_strlcat(msg, _("\" "), SH_MSG_BUF);
3623#else
3624 sl_strlcat(msg, _(">"), SH_MSG_BUF);
3625#endif
3626 }
3627 }
3628
3629 tmp_path = sh_util_safe_name(theFile->fullpath);
3630 sh_error_handle(log_severity, FIL__, __LINE__,
3631 (long) modi_mask, MSG_FI_CHAN,
3632 (policy_override == NULL) ? _(policy[class]):log_policy,
3633 change_code, tmp_path, msg);
3634
3635 SH_FREE(tmp_path);
3636 SH_FREE(tmp);
3637 SH_FREE(msg);
3638
3639#ifndef REPLACE_OLD
3640 SET_SH_FFLAG_REPORTED(p->fflags);
3641#endif
3642
3643 if (S_TRUE == sh.flag.update)
3644 {
3645 if (S_FALSE == sh_util_ask_update(theFile->fullpath))
3646 {
3647 /* user does not want to update, thus we replace
3648 * with data from the baseline database
3649 */
3650 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
3651 theFile->mode = p->theFile.mode;
3652#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3653 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
3654 theFile->attributes = p->theFile.attributes;
3655#endif
3656#if defined(USE_ACL) || defined(USE_XATTR)
3657 if (theFile->attr_string == NULL && p->attr_string != NULL)
3658 { theFile->attr_string = sh_util_strdup (p->attr_string); }
3659 else if (theFile->attr_string != NULL && p->attr_string == NULL)
3660 { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
3661 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3662 {
3663 if (0 != strcmp(theFile->attr_string, p->attr_string))
3664 {
3665 SH_FREE(theFile->attr_string);
3666 theFile->attr_string = sh_util_strdup (p->attr_string);
3667 }
3668 }
3669#endif
3670
3671 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
3672 {
3673 if (theFile->link_path)
3674 SH_FREE(theFile->link_path);
3675 if (p->linkpath)
3676 theFile->link_path = sh_util_strdup(p->linkpath);
3677 else
3678 theFile->link_path = sh_util_strdup("-");
3679 }
3680 else
3681 {
3682 if (theFile->link_path)
3683 SH_FREE(theFile->link_path);
3684 if (p->linkpath && p->linkpath != notalink)
3685 theFile->link_path = sh_util_strdup(p->linkpath);
3686 else
3687 theFile->link_path = NULL;
3688 }
3689
3690 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
3691
3692 theFile->mtime = p->theFile.mtime;
3693 theFile->ctime = p->theFile.ctime;
3694 theFile->atime = p->theFile.atime;
3695
3696 theFile->size = p->theFile.size;
3697
3698 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
3699 theFile->group = p->theFile.group;
3700 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
3701 theFile->owner = p->theFile.owner;
3702
3703 theFile->ino = p->theFile.ino;
3704 theFile->rdev = p->theFile.rdev;
3705 theFile->dev = p->theFile.dev;
3706 theFile->hardlinks = p->theFile.hardlinks;
3707
3708 SET_SH_FFLAG_VISITED(p->fflags);
3709 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3710 retval = 1;
3711 goto unlock_and_return;
3712 }
3713 else /* if (sh.flag.reportonce == S_TRUE) */
3714 {
3715 /* we replace the data in the in-memory copy of the
3716 * baseline database, because otherwise we would get
3717 * another warning if the suidcheck runs
3718 */
3719 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3720 p->theFile.mode = theFile->mode;
3721#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3722 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
3723 p->theFile.attributes = theFile->attributes;
3724#endif
3725#if defined(USE_ACL) || defined(USE_XATTR)
3726 if (p->attr_string == NULL && theFile->attr_string != NULL)
3727 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3728 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3729 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3730 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3731 {
3732 if (0 != strcmp(theFile->attr_string, p->attr_string))
3733 {
3734 SH_FREE(p->attr_string);
3735 p->attr_string = sh_util_strdup (theFile->attr_string);
3736 }
3737 }
3738#endif
3739
3740 if (theFile->c_mode[0] == 'l' || theFile->link_path)
3741 {
3742 if (p->linkpath != NULL && p->linkpath != notalink)
3743 SH_FREE(p->linkpath);
3744 p->linkpath = sh_util_strdup(theFile->link_path);
3745 }
3746 else
3747 {
3748 if (p->linkpath != NULL && p->linkpath != notalink) {
3749 SH_FREE(p->linkpath);
3750 }
3751 p->linkpath = (char *)notalink;
3752 }
3753
3754 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3755
3756 p->theFile.mtime = theFile->mtime;
3757 p->theFile.ctime = theFile->ctime;
3758 p->theFile.atime = theFile->atime;
3759
3760 p->theFile.size = theFile->size;
3761
3762 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3763 p->theFile.group = theFile->group;
3764 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3765 p->theFile.owner = theFile->owner;
3766
3767 p->theFile.ino = theFile->ino;
3768 p->theFile.rdev = theFile->rdev;
3769 p->theFile.dev = theFile->dev;
3770 p->theFile.hardlinks = theFile->hardlinks;
3771 }
3772 }
3773 }
3774
3775 SET_SH_FFLAG_VISITED(p->fflags);
3776 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3777
3778 unlock_and_return:
3779 ; /* 'label at end of compound statement */
3780 SH_MUTEX_UNLOCK(mutex_hash);
3781 SL_RETURN(retval, _("sh_hash_compdata"));
3782}
3783
3784int hash_full_tree ()
3785{
3786 sh_file_t * p;
3787 int i;
3788
3789 SL_ENTER(_("sh_hash_compdata"));
3790
3791 if (IsInit != 1)
3792 SL_RETURN(0, _("sh_hash_compdata"));
3793
3794 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
3795 for (i = 0; i < TABSIZE; ++i)
3796 {
3797 for (p = tab[i]; p; p = p->next)
3798 CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
3799 }
3800 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
3801 SL_RETURN (0, _("sh_hash_compdata"));
3802}
3803
3804
3805int hash_remove_tree (char * s)
3806{
3807 sh_file_t * p;
3808 size_t len;
3809 unsigned int i;
3810
3811 SL_ENTER(_("hash_remove_tree"));
3812
3813 if (!s || *s == '\0')
3814 SL_RETURN ((-1), _("hash_remove_tree"));
3815
3816 len = sl_strlen(s);
3817
3818 if (IsInit != 1)
3819 sh_hash_init();
3820
3821 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
3822 for (i = 0; i < TABSIZE; ++i)
3823 {
3824 for (p = tab[i]; p; p = p->next)
3825 {
3826 if (p->fullpath && 0 == strncmp(s, p->fullpath, len))
3827 {
3828 SET_SH_FFLAG_ALLIGNORE(p->fflags);
3829 }
3830 }
3831 }
3832 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
3833 SL_RETURN ((0), _("hash_remove_tree"));
3834}
3835
3836#if TIME_WITH_SYS_TIME
3837#include <sys/time.h>
3838#include <time.h>
3839#else
3840#if HAVE_SYS_TIME_H
3841#include <sys/time.h>
3842#else
3843#include <time.h>
3844#endif
3845#endif
3846
3847static int ListFullDetail = S_FALSE;
3848static int ListWithDelimiter = S_FALSE;
3849static char * ListFile = NULL;
3850
3851int set_list_file (const char * c)
3852{
3853 ListFile = sh_util_strdup(c);
3854 return 0;
3855}
3856
3857int set_full_detail (const char * c)
3858{
3859 (void) c;
3860 ListFullDetail = S_TRUE;
3861 return 0;
3862}
3863
3864int set_list_delimited (const char * c)
3865{
3866 (void) c;
3867 ListFullDetail = S_TRUE;
3868 ListWithDelimiter = S_TRUE;
3869 return 0;
3870}
3871
3872/* Always quote the string, except if it is empty. Quote quotes by
3873 * doubling them.
3874 */
3875char * csv_escape(const char * str)
3876{
3877 const char * p = str;
3878 const char * q;
3879
3880 size_t size = 0;
3881 size_t flag_quote = 0;
3882
3883 char * new;
3884 char * pnew;
3885
3886 if (p)
3887 {
3888
3889 while (*p)
3890 {
3891 if (*p == '"')
3892 ++flag_quote;
3893
3894 ++size; ++p;
3895 }
3896
3897 if (sl_ok_adds(size, flag_quote))
3898 size += flag_quote; /* double each quote */
3899 else
3900 return NULL;
3901
3902 if (sl_ok_adds(size, 3))
3903 size += 3; /* two quotes and terminating null */
3904 else
3905 return NULL;
3906
3907 new = SH_ALLOC(size);
3908
3909 if (flag_quote != 0)
3910 {
3911 new[0] = '"';
3912 pnew = &new[1];
3913 q = str;
3914 while (*q)
3915 {
3916 *pnew = *q;
3917 if (*pnew == '"')
3918 {
3919 ++pnew; *pnew = '"';
3920 }
3921 ++pnew; ++q;
3922 }
3923 *pnew = '"'; ++pnew;
3924 *pnew = '\0';
3925 }
3926 else
3927 {
3928 if (size > 3)
3929 {
3930 new[0] = '"';
3931 sl_strlcpy (&new[1], str, size-1);
3932 new[size-2] = '"';
3933 new[size-1] = '\0';
3934 }
3935 else
3936 {
3937 new[0] = '\0';
3938 }
3939 }
3940
3941 return new;
3942 }
3943 return NULL;
3944}
3945
3946
3947
3948void sh_hash_list_db_entry_full_detail (sh_file_t * p)
3949{
3950 char * tmp;
3951 char * esc;
3952 char str[81];
3953
3954 if (ListWithDelimiter == S_TRUE)
3955 {
3956 printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "),
3957 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3958 p->theFile.c_mode, (int) p->theFile.mode,
3959 p->theFile.c_attributes, (int) p->theFile.attributes,
3960 (int) p->theFile.hardlinks,
3961 p->theFile.c_owner, (int) p->theFile.owner,
3962 p->theFile.c_group, (int) p->theFile.group);
3963 }
3964 else
3965 {
3966 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
3967 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3968 p->theFile.c_mode, (int) p->theFile.mode,
3969 p->theFile.c_attributes, (int) p->theFile.attributes,
3970 (int) p->theFile.hardlinks,
3971 p->theFile.c_owner, (int) p->theFile.owner,
3972 p->theFile.c_group, (int) p->theFile.group);
3973 }
3974
3975 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3976 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev);
3977 else
3978 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size);
3979
3980 printf( _(" %8s"), str);
3981 if (ListWithDelimiter == S_TRUE)
3982 putchar(',');
3983
3984 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str)));
3985 if (ListWithDelimiter == S_TRUE)
3986 putchar(',');
3987 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str)));
3988 if (ListWithDelimiter == S_TRUE)
3989 putchar(',');
3990 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str)));
3991 if (ListWithDelimiter == S_TRUE)
3992 putchar(',');
3993 printf( _(" %s"), p->theFile.checksum);
3994 if (ListWithDelimiter == S_TRUE)
3995 putchar(',');
3996
3997 tmp = sh_util_safe_name(p->fullpath);
3998 if (ListWithDelimiter != S_TRUE)
3999 {
4000 printf( _(" %s"), tmp);
4001 }
4002 else
4003 {
4004 esc = csv_escape(tmp);
4005 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
4006 if (esc)
4007 SH_FREE(esc);
4008 }
4009 SH_FREE(tmp);
4010
4011 if ('l' == p->theFile.c_mode[0])
4012 {
4013 tmp = sh_util_safe_name(p->linkpath);
4014 if (ListWithDelimiter != S_TRUE)
4015 {
4016 printf(_(" -> %s"), tmp);
4017 }
4018 else
4019 {
4020 esc = csv_escape(tmp);
4021 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
4022 if (esc)
4023 SH_FREE(esc);
4024 }
4025 SH_FREE(tmp);
4026 }
4027
4028 if (p->attr_string)
4029 {
4030 tmp = sh_util_safe_name(p->attr_string);
4031 if (ListWithDelimiter != S_TRUE)
4032 {
4033 printf(_(" %s"), tmp);
4034 }
4035 else
4036 {
4037 esc = csv_escape(tmp);
4038 printf( _(" %s"), (esc != NULL) ? esc : _("(null)"));
4039 if (esc)
4040 SH_FREE(esc);
4041 }
4042 SH_FREE(tmp);
4043 }
4044 else
4045 {
4046 if (ListWithDelimiter == S_TRUE)
4047 printf("%s",_(" no_attr"));
4048 }
4049 putchar('\n');
4050
4051 return;
4052}
4053
4054void sh_hash_list_db_entry (sh_file_t * p)
4055{
4056 char nowtime[128];
4057 char thetime[128];
4058 char * tmp;
4059 time_t now = time(NULL);
4060 time_t then = (time_t) p->theFile.mtime;
4061
4062#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
4063 struct tm * time_ptr;
4064 struct tm time_tm;
4065
4066 time_ptr = gmtime_r(&then, &time_tm);
4067 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
4068 time_ptr = gmtime_r(&now, &time_tm);
4069 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
4070 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
4071 {
4072 time_ptr = gmtime_r(&then, &time_tm);
4073 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
4074 }
4075#else
4076 strftime(thetime, 127, _("%b %d %Y"), gmtime(&then));
4077 strftime(nowtime, 127, _("%b %d %Y"), gmtime(&now));
4078 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
4079 strftime(thetime, 127, _("%b %d %H:%M"), gmtime(&then));
4080#endif
4081
4082 tmp = sh_util_safe_name(p->fullpath);
4083 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
4084 printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"),
4085 p->theFile.c_mode, (int) p->theFile.hardlinks,
4086 p->theFile.c_owner, p->theFile.c_group,
4087 (int) major((dev_t)p->theFile.rdev),
4088 (int) minor((dev_t)p->theFile.rdev),
4089 thetime,
4090 tmp);
4091 else
4092 printf(_("%10s %3d %-8s %-8s %8ld %s %s"),
4093 p->theFile.c_mode, (int) p->theFile.hardlinks,
4094 p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size,
4095 thetime,
4096 tmp);
4097 SH_FREE(tmp);
4098
4099 if ('l' == p->theFile.c_mode[0])
4100 {
4101 tmp = sh_util_safe_name(p->linkpath);
4102 printf(_(" -> %s\n"), tmp);
4103 SH_FREE(tmp);
4104 }
4105 else
4106 printf("\n");
4107
4108 return;
4109}
4110
4111#ifdef HAVE_LIBZ
4112#include <zlib.h>
4113#endif
4114
4115int sh_hash_printcontent(char * linkpath)
4116{
4117#ifdef HAVE_LIBZ
4118 unsigned char * decoded;
4119 unsigned char * decompressed = NULL;
4120 size_t dlen;
4121 unsigned long clen;
4122 unsigned long clen_o;
4123 int res;
4124
4125 if (linkpath && *linkpath != '-')
4126 {
4127 dlen = sh_util_base64_dec_alloc (&decoded,
4128 (unsigned char *)linkpath,
4129 strlen(linkpath));
4130
4131 clen = dlen * 2 + 1;
4132
4133 do {
4134 if (decompressed)
4135 SH_FREE(decompressed);
4136 clen += dlen; clen_o = clen;
4137 decompressed = SH_ALLOC(clen);
4138 res = uncompress(decompressed, &clen, decoded, dlen);
4139 if (res == Z_MEM_ERROR)
4140 { fprintf(stderr, "%s",_("Error: Not enough memory\n")); return -1; }
4141 if (res == Z_DATA_ERROR)
4142 { fprintf(stderr, "%s",_("Error: Data corrupt or incomplete\n")); return -1; }
4143 } while (res == Z_BUF_ERROR || clen == clen_o);
4144
4145 decompressed[clen] = '\0';
4146 fputs( (char*) decompressed, stdout);
4147 SH_FREE(decompressed);
4148 return 0;
4149 }
4150#else
4151 (void) linkpath;
4152#endif
4153 fprintf(stderr, "%s",_("Error: No data available\n"));
4154 return -1;
4155}
4156
4157int sh_hash_list_db (const char * db_file)
4158{
4159 sh_file_t * p;
4160 SL_TICKET fd;
4161 char * line;
4162 int flag = 0;
4163
4164 if (!db_file)
4165 {
4166 _exit(EXIT_FAILURE);
4167 return -1;
4168 }
4169 if (sl_is_suid())
4170 {
4171 fprintf(stderr, "%s",_("ERROR: insufficient privilege\n"));
4172 _exit (EXIT_FAILURE);
4173 return -1; /* for Mac OSX compiler */
4174 }
4175 if (0 == strcmp(db_file, _("default")))
4176 db_file = file_path('D', 'W');
4177 if (!db_file)
4178 {
4179 _exit(EXIT_FAILURE);
4180 return -1;
4181 }
4182
4183 line = SH_ALLOC(MAX_PATH_STORE+2);
4184
4185 if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, db_file, SL_YESPRIV)))
4186 {
4187 fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"),
4188 db_file, fd);
4189 _exit(EXIT_FAILURE);
4190 return -1;
4191 }
4192
4193 /* fast forward to start of data
4194 */
4195 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, db_file);
4196
4197 while (1)
4198 {
4199 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
4200 if ((p != NULL) && (p->fullpath[0] == '/'))
4201 {
4202 if (!ListFile)
4203 {
4204 flag = 1;
4205 if (ListFullDetail == S_FALSE)
4206 sh_hash_list_db_entry (p);
4207 else
4208 sh_hash_list_db_entry_full_detail (p);
4209 }
4210 else
4211 {
4212 if (0 != sl_strcmp(ListFile, p->fullpath))
4213 {
4214 continue;
4215 }
4216 flag = 1;
4217 if ('l' != p->theFile.c_mode[0])
4218 {
4219 if (sh_hash_printcontent(p->linkpath) < 0)
4220 {
4221 _exit(EXIT_FAILURE);
4222 return -1;
4223 }
4224 }
4225 else
4226 {
4227 fprintf(stderr, "%s",_("File is a link\n"));
4228 _exit(EXIT_FAILURE);
4229 return -1;
4230 }
4231 break;
4232 }
4233 }
4234 else if (p == NULL)
4235 {
4236 break;
4237 }
4238 }
4239
4240 if (line != NULL)
4241 SH_FREE(line);
4242 sl_close (fd);
4243
4244 fflush(NULL);
4245
4246 if (flag == 0)
4247 {
4248 fprintf(stderr, "%s",_("File not found\n"));
4249 _exit(EXIT_FAILURE);
4250 }
4251 _exit(EXIT_SUCCESS);
4252 return 0;
4253}
4254
4255/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
4256#endif
Note: See TracBrowser for help on using the repository browser.