source: trunk/src/sh_hash.c@ 362

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

Fix for ticket #267 (Multiple compiler warnings with gcc 4.6.1).

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