source: trunk/src/sh_hash.c@ 445

Last change on this file since 445 was 444, checked in by katerina, 11 years ago

Support for sha2-256 checksum (ticket #348).

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