source: trunk/src/sh_hash.c@ 182

Last change on this file since 182 was 181, checked in by katerina, 16 years ago

Remove support for obsolete version 0.8 of libprelude (ticket #120).

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