source: trunk/src/sh_hash.c@ 356

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

Patch for ticket #261: show policy for checked files in verbose mode.

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