source: trunk/src/sh_hash.c@ 327

Last change on this file since 327 was 320, checked in by katerina, 14 years ago

Fix for ticket #237: Potential deadlock in sh_hash_hashdelete()

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