source: trunk/src/sh_hash.c@ 303

Last change on this file since 303 was 294, checked in by katerina, 14 years ago

Tikets #213 and #214 (Use auditd to determine who changed a file, Windows registry check).

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