source: trunk/src/sh_hash.c@ 395

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

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

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