source: trunk/src/sh_hash.c@ 308

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

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

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