source: trunk/src/sh_hash.c@ 206

Last change on this file since 206 was 205, checked in by katerina, 16 years ago

New option LooseDirCheck (ticket #132). Also, replace _exit() with raise(SIGKILL).

File size: 98.6 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 volatile int retval = 0;
1142 volatile int exitval = EXIT_SUCCESS;
1143
1144 SL_ENTER(_("sh_hash_init"));
1145
1146 SH_MUTEX_LOCK(mutex_hash);
1147
1148#if defined(WITH_GPG) || defined(WITH_PGP)
1149 flag_pgp = S_FALSE;
1150 flag_nohead = S_FALSE;
1151#endif
1152
1153 if (IsInit == 1)
1154 {
1155 goto unlock_and_return;
1156 }
1157
1158 fd = (-1);
1159
1160#if defined(SH_WITH_CLIENT)
1161
1162 /* Data file from Server
1163 */
1164
1165 if (fd == (-1) && 0 == sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
1166 {
1167 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_D_DSTART);
1168 fd = sh_forward_req_file(_("DATA"));
1169 if (SL_ISERROR(fd))
1170 {
1171 dlog(1, FIL__, __LINE__,
1172 _("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);
1173 sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1,
1174 sh.prg_name);
1175 retval = 1; exitval = EXIT_FAILURE;
1176 goto unlock_and_return;
1177 }
1178 sl_rewind (fd);
1179
1180 sl_strlcpy (sh.data.hash,
1181 sh_tiger_hash (file_path('C', 'R'),
1182 fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
1183 KEY_LEN+1);
1184 sl_rewind (fd);
1185 }
1186 else
1187#endif
1188 /* Local data file
1189 */
1190
1191 if (fd == (-1))
1192 {
1193 if ( SL_ISERROR(fd = sl_open_read(file_path('D', 'R'), SL_YESPRIV)))
1194 {
1195 TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s>\n"),
1196 file_path('D', 'R')));
1197 dlog(1, FIL__, __LINE__,
1198 _("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"),
1199 sl_get_errmsg(), fd, (int) sl_ret_euid());
1200 sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1,
1201 sh.prg_name);
1202 retval = 1; exitval = EXIT_FAILURE;
1203 goto unlock_and_return;
1204 }
1205
1206 TPT(( 0, FIL__, __LINE__, _("msg=<Opened database: %s>\n"),
1207 file_path('D', 'R')));
1208
1209 if (0 != sl_strncmp(sh.data.hash,
1210 sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
1211 hashbuf, sizeof(hashbuf)),
1212 KEY_LEN)
1213 && sh.flag.checkSum != SH_CHECK_INIT)
1214 {
1215 dlog(1, FIL__, __LINE__,
1216 _("The checksum of the file signature database has changed since startup: %s -> %s\n"),
1217 sh.data.hash, sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
1218 hashbuf, sizeof(hashbuf)));
1219 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH,
1220 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1221 file_path('D', 'R') )
1222 );
1223 retval = 1; exitval = EXIT_FAILURE;
1224 goto unlock_and_return;
1225 }
1226 sl_rewind (fd);
1227
1228 } /* new 1.4.8 */
1229
1230 if (sig_termfast == 1) /* SIGTERM */
1231 {
1232 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1233 --sig_raised; --sig_urgent;
1234 retval = 1; exitval = EXIT_SUCCESS;
1235 goto unlock_and_return;
1236 }
1237
1238#if defined(WITH_GPG) || defined(WITH_PGP)
1239 /* new 1.4.8: also checked for server data */
1240
1241 /* extract the data and copy to temporary file
1242 */
1243 fdTmp = open_tmp();
1244
1245 fin_cp = fdopen(get_the_fd(fd), "rb");
1246 buf = SH_ALLOC(FGETS_BUF);
1247
1248 while (NULL != fgets(buf, FGETS_BUF, fin_cp))
1249 {
1250 bufc = 0;
1251 while (bufc < FGETS_BUF) {
1252 if (buf[bufc] == '\n') { ++bufc; break; }
1253 ++bufc;
1254 }
1255
1256 if (sig_termfast == 1) /* SIGTERM */
1257 {
1258 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1259 --sig_raised; --sig_urgent;
1260 retval = 1; exitval = EXIT_SUCCESS;
1261 goto unlock_and_return;
1262 }
1263
1264 if (flag_pgp == S_FALSE &&
1265 (0 == sl_strcmp(buf, _("-----BEGIN PGP SIGNED MESSAGE-----\n"))||
1266 0 == sl_strcmp(buf, _("-----BEGIN PGP MESSAGE-----\n")))
1267 )
1268 {
1269 flag_pgp = S_TRUE;
1270 sl_write(fdTmp, buf, bufc);
1271 continue;
1272 }
1273
1274 if (flag_pgp == S_TRUE && flag_nohead == S_FALSE)
1275 {
1276 if (buf[0] == '\n')
1277 {
1278 flag_nohead = S_TRUE;
1279 sl_write(fdTmp, buf, 1);
1280 continue;
1281 }
1282 else if (0 == sl_strncmp(buf, _("Hash:"), 5) ||
1283 0 == sl_strncmp(buf, _("NotDashEscaped:"), 15))
1284 {
1285 sl_write(fdTmp, buf, bufc);
1286 continue;
1287 }
1288 else
1289 continue;
1290 }
1291
1292 if (flag_pgp == S_TRUE && buf[0] == '\n')
1293 {
1294 sl_write(fdTmp, buf, 1);
1295 }
1296 else if (flag_pgp == S_TRUE)
1297 {
1298 /* sl_write_line(fdTmp, buf, bufc); */
1299 sl_write(fdTmp, buf, bufc);
1300 }
1301
1302 if (flag_pgp == S_TRUE &&
1303 0 == sl_strcmp(buf, _("-----END PGP SIGNATURE-----\n")))
1304 break;
1305 }
1306 SH_FREE(buf);
1307 sl_close(fd);
1308 fclose(fin_cp);
1309
1310 fd = fdTmp;
1311 sl_rewind (fd);
1312
1313 /* Validate signature of open file.
1314 */
1315 if (0 != sh_gpg_check_sign (0, fd, 2))
1316 {
1317 retval = 1; exitval = EXIT_FAILURE;
1318 goto unlock_and_return;
1319 }
1320 sl_rewind (fd);
1321#endif
1322 /* } new 1.4.8 check sig also for files downloaded from server */
1323
1324 line = SH_ALLOC(MAX_PATH_STORE+2);
1325
1326 /* fast forward to start of data
1327 */
1328 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, file_path('D', 'R'));
1329
1330 for (i = 0; i < TABSIZE; ++i)
1331 tab[i] = NULL;
1332
1333 while (1)
1334 {
1335 if (sig_termfast == 1) /* SIGTERM */
1336 {
1337 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1338 --sig_raised; --sig_urgent;
1339 retval = 1; exitval = EXIT_SUCCESS;
1340 goto unlock_and_return;
1341 }
1342
1343 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
1344 if (p != NULL)
1345 {
1346 hashinsert (p);
1347 ++count;
1348 }
1349 else
1350 break;
1351 }
1352
1353 /* Initialization completed.
1354 */
1355 IsInit = 1;
1356
1357 if (line != NULL)
1358 SH_FREE(line);
1359
1360 /* Always keep db in memory, so we have no open file
1361 */
1362 sl_close (fd);
1363 sh_hash_getline_end();
1364 fd = -1;
1365
1366 unlock_and_return:
1367 ; /* 'label at end of compound statement */
1368 SH_MUTEX_UNLOCK(mutex_hash);
1369 if (retval == 0)
1370 {
1371 SL_RET0(_("sh_hash_init"));
1372 }
1373 aud_exit (FIL__, __LINE__, exitval);
1374}
1375
1376/*****************************************************************
1377 *
1378 * delete hash array
1379 *
1380 *****************************************************************/
1381void sh_hash_hashdelete ()
1382{
1383 int i;
1384
1385 SL_ENTER(_("sh_hash_hashdelete"));
1386 SH_MUTEX_LOCK(mutex_hash);
1387
1388 if (IsInit == 0)
1389 goto unlock_and_exit;
1390
1391 for (i = 0; i < TABSIZE; ++i)
1392 if (tab[i] != NULL)
1393 {
1394 hash_kill (tab[i]);
1395 tab[i] = NULL;
1396 }
1397 IsInit = 0;
1398
1399 unlock_and_exit:
1400 ; /* 'label at end of compound statement */
1401 SH_MUTEX_UNLOCK(mutex_hash);
1402 SL_RET0(_("sh_hash_hashdelete"));
1403}
1404
1405/******************************************************************
1406 *
1407 * Insert a file into the database.
1408 *
1409 ******************************************************************/
1410static int pushdata_isfirst = 1;
1411static SL_TICKET pushdata_fd = -1;
1412
1413static int pushdata_stdout = S_FALSE;
1414
1415static char * sh_db_version_string = NULL;
1416
1417int sh_hash_pushdata_stdout (const char * str)
1418{
1419 if (!str)
1420 { pushdata_stdout = S_TRUE; return 0; }
1421 return -1;
1422}
1423
1424int sh_hash_version_string(const char * str)
1425{
1426 if (str)
1427 {
1428 if (sh_db_version_string != NULL) {
1429 SH_FREE(sh_db_version_string);
1430 }
1431 if (0 == sl_strncmp(str, _("NULL"), 4))
1432 {
1433 sh_db_version_string = NULL;
1434 return 0;
1435 }
1436 sh_db_version_string = sh_util_strdup(str);
1437 return 0;
1438 }
1439 return -1;
1440}
1441
1442static int sh_loosedircheck = S_FALSE;
1443
1444int sh_hash_loosedircheck(const char * str)
1445{
1446 return sh_util_flagval(str, &sh_loosedircheck);
1447}
1448
1449
1450static void sh_hash_pushdata_int (file_type * buf, char * fileHash)
1451{
1452 static long p_count = 0;
1453
1454 int status = 0;
1455
1456 char * tmp;
1457 size_t tmp_len = 0;
1458 size_t old_len = 0;
1459 size_t path_len = 0;
1460
1461 sh_filestore_t p;
1462
1463 struct stat sbuf;
1464
1465 char * fullpath = NULL;
1466 char * linkpath = NULL;
1467 char * attr_string = NULL;
1468
1469 char * line = NULL;
1470
1471 char timestring[81];
1472
1473#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
1474 int i;
1475#endif
1476
1477 SL_ENTER(_("sh_hash_pushdata_int"));
1478
1479 fullpath = SH_ALLOC(MAX_PATH_STORE+1);
1480 linkpath = SH_ALLOC(MAX_PATH_STORE+1);
1481
1482 linkpath[0] = '-';
1483 linkpath[1] = '\0';
1484 fullpath[0] = '-';
1485 fullpath[1] = '\0';
1486
1487 if (!buf) {
1488 memset(&p, '\0', sizeof(sh_filestore_t));
1489 }
1490
1491 if ((pushdata_stdout == S_TRUE) && (sh.flag.update == S_TRUE))
1492 {
1493 dlog(1, FIL__, __LINE__,
1494 _("You cannot write the database to stdout when you use update rather than init.\n"));
1495 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1496 _("Writing database to stdout with update"),
1497 sh.prg_name,
1498 _("sh_hash_pushdata_int"));
1499 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1500 }
1501
1502 if ((pushdata_stdout == S_TRUE) && (sl_is_suid()))
1503 {
1504 dlog(1, FIL__, __LINE__,
1505 _("You cannot write the database to stdout when running with suid privileges.\n"));
1506 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1507 _("Writing database to stdout when suid"),
1508 sh.prg_name,
1509 _("sh_hash_pushdata_int"));
1510 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1511 }
1512
1513
1514 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) &&
1515 ( (NULL == file_path('D', 'W')) ||
1516 (0 == sl_strcmp(file_path('D', 'W'), _("REQ_FROM_SERVER"))) ))
1517 {
1518 dlog(1, FIL__, __LINE__,
1519 _("You need to configure a local path for initializing the database\nlike ./configure --with-data-file=REQ_FROM_SERVER/some/local/path\n"));
1520 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1521 _("No local path for database specified"),
1522 sh.prg_name,
1523 _("sh_hash_pushdata_int"));
1524 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1525 }
1526
1527
1528 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE))
1529 {
1530 /* Warn that file already exists; file_path != NULL here because
1531 * checked above
1532 */
1533 if (0 == retry_lstat(FIL__, __LINE__, file_path('D', 'W'), &sbuf))
1534 {
1535 if (sh.flag.update == S_FALSE)
1536 {
1537 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_FI_DBEX,
1538 file_path('D', 'W'));
1539 }
1540 }
1541 }
1542
1543
1544 if (sh.flag.update == S_FALSE)
1545 {
1546 if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
1547 {
1548 if ( SL_ISERROR(pushdata_fd = sl_open_write(file_path('D', 'W'), SL_YESPRIV)))
1549 {
1550 SH_FREE(fullpath);
1551 SH_FREE(linkpath);
1552 sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
1553 geteuid(), file_path('D', 'W'));
1554 SL_RET0(_("sh_hash_pushdata_int"));
1555 }
1556 if ( SL_ISERROR(status = sl_forward(pushdata_fd)))
1557 {
1558 SH_FREE(fullpath);
1559 SH_FREE(linkpath);
1560 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1561 _("Fast forward failed"), _("sh_hash_pushdata_int"),
1562 file_path('D', 'W'));
1563 SL_RET0(_("sh_hash_pushdata_int"));
1564 }
1565 }
1566 }
1567 else /* update == TRUE */
1568 {
1569 if (pushdata_isfirst == 1)
1570 {
1571 TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")))
1572 if ( SL_ISERROR(pushdata_fd = sl_open_rdwr(file_path('D', 'W'), SL_YESPRIV))){
1573 SH_FREE(fullpath);
1574 SH_FREE(linkpath);
1575 sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
1576 geteuid(), file_path('D', 'W'));
1577 SL_RET0(_("sh_hash_pushdata_int"));
1578 }
1579 line = SH_ALLOC(MAX_PATH_STORE+1);
1580 if (SL_ISERROR(sh_hash_setdataent_old (pushdata_fd, line,
1581 MAX_PATH_STORE,
1582 file_path('D', 'W'))))
1583 {
1584 SH_FREE(fullpath);
1585 SH_FREE(linkpath);
1586 SH_FREE(line);
1587 SL_RET0(_("sh_hash_pushdata_int"));
1588 }
1589 SH_FREE(line);
1590 }
1591 }
1592
1593 if (buf != NULL && buf->fullpath != NULL) {
1594
1595 old_len = sl_strlen(buf->fullpath);
1596#if defined(SH_STEALTH)
1597 sh_do_encode(buf->fullpath, old_len);
1598#endif
1599 tmp = quote_string(buf->fullpath, old_len);
1600 tmp_len = sl_strlen(tmp);
1601#if defined(SH_STEALTH)
1602 sh_do_decode(buf->fullpath, old_len);
1603#endif
1604
1605 if (tmp && tmp_len <= MAX_PATH_STORE)
1606 {
1607 sl_strlcpy(fullpath, buf->fullpath, MAX_PATH_STORE+1);
1608 }
1609 else
1610 {
1611 char hashbuf[KEYBUF_SIZE];
1612
1613 sl_strlcpy(fullpath,
1614 sh_tiger_hash (buf->fullpath,
1615 TIGER_DATA, old_len,
1616 hashbuf, sizeof(hashbuf)),
1617 KEY_LEN+1);
1618 }
1619 if (tmp) SH_FREE(tmp);
1620 }
1621
1622 path_len = sl_strlen(fullpath);
1623#if defined(SH_STEALTH)
1624 sh_do_encode(fullpath, path_len);
1625#endif
1626
1627 tmp = quote_string(fullpath, path_len);
1628 if (tmp) {
1629 sl_strlcpy(fullpath, tmp, MAX_PATH_STORE+1);
1630 SH_FREE(tmp);
1631 }
1632
1633 if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL)
1634 {
1635
1636 old_len = sl_strlen(buf->link_path);
1637#if defined(SH_STEALTH)
1638 if (buf->c_mode[0] == 'l')
1639 sh_do_encode(buf->link_path, old_len);
1640#endif
1641 tmp = quote_string(buf->link_path, old_len);
1642 tmp_len = sl_strlen(tmp);
1643#if defined(SH_STEALTH)
1644 if (buf->c_mode[0] == 'l')
1645 sh_do_decode(buf->link_path, old_len);
1646#endif
1647
1648 if (tmp && tmp_len <= MAX_PATH_STORE)
1649 {
1650 sl_strlcpy(linkpath, buf->link_path, MAX_PATH_STORE+1);
1651 }
1652 else
1653 {
1654 char hashbuf[KEYBUF_SIZE];
1655 sl_strlcpy(linkpath,
1656 sh_tiger_hash (buf->link_path,
1657 TIGER_DATA, old_len,
1658 hashbuf, sizeof(hashbuf)),
1659 KEY_LEN+1);
1660 }
1661 if (tmp) SH_FREE(tmp);
1662
1663 path_len = sl_strlen(linkpath);
1664#if defined(SH_STEALTH)
1665 if (buf->c_mode[0] == 'l')
1666 sh_do_encode(linkpath, path_len);
1667#endif
1668 tmp = quote_string(linkpath, path_len);
1669 if (tmp)
1670 {
1671 sl_strlcpy(linkpath, tmp, MAX_PATH_STORE+1);
1672 SH_FREE(tmp);
1673 }
1674 }
1675
1676 if (buf != NULL && buf->attr_string != NULL)
1677 {
1678 old_len = sl_strlen(buf->attr_string);
1679#if defined(SH_STEALTH)
1680 sh_do_encode(buf->attr_string, old_len);
1681#endif
1682 tmp = quote_string(buf->attr_string, old_len);
1683 if (tmp)
1684 {
1685 attr_string = tmp;
1686 tmp = NULL;
1687 }
1688#if defined(SH_STEALTH)
1689 sh_do_decode(buf->attr_string, old_len);
1690#endif
1691 }
1692
1693
1694 if (buf != NULL) {
1695 p.mark = REC_MAGIC;
1696 if (attr_string)
1697 p.mark |= REC_FLAGS_ATTR;
1698 sl_strlcpy(p.c_mode, buf->c_mode, CMODE_SIZE);
1699 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
1700 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
1701 if (fileHash) {
1702 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
1703 }
1704#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1705 sl_strlcpy(p.c_attributes, buf->c_attributes, ATTRBUF_SIZE);
1706#else
1707 for (i = 0; i < ATTRBUF_USED; ++i) p.c_attributes[i] = '-';
1708 p.c_attributes[ATTRBUF_USED] = '\0';
1709#endif
1710
1711#if defined(SH_STEALTH)
1712 sh_do_encode(p.c_mode, sl_strlen(p.c_mode));
1713 sh_do_encode(p.c_owner, sl_strlen(p.c_owner));
1714 sh_do_encode(p.c_group, sl_strlen(p.c_group));
1715 sh_do_encode(p.checksum, sl_strlen(p.checksum));
1716
1717 sh_do_encode(p.c_attributes, sl_strlen(p.c_attributes));
1718#endif
1719
1720#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1721 p.attributes = (UINT32) buf->attributes;
1722#else
1723 p.attributes = 0;
1724#endif
1725 p.linkmode = (UINT32) buf->linkmode;
1726 p.hardlinks = (UINT32) buf->hardlinks;
1727 p.dev = (UINT64) buf->dev;
1728 p.rdev = (UINT64) buf->rdev;
1729 p.mode = (UINT32) buf->mode;
1730 p.ino = (UINT32) buf->ino;
1731 p.size = (UINT64) buf->size;
1732 p.mtime = (UINT64) buf->mtime;
1733 p.atime = (UINT64) buf->atime;
1734 p.ctime = (UINT64) buf->ctime;
1735 p.owner = (UINT32) buf->owner;
1736 p.group = (UINT32) buf->group;
1737
1738 swap_32(&(p.mode));
1739 swap_32(&(p.linkmode));
1740 swap_64(&(p.dev));
1741 swap_64(&(p.rdev));
1742 swap_32(&(p.hardlinks));
1743 swap_32(&(p.ino));
1744 swap_64(&(p.size));
1745 swap_64(&(p.atime));
1746 swap_64(&(p.mtime));
1747 swap_64(&(p.ctime));
1748 swap_32(&(p.owner));
1749 swap_32(&(p.group));
1750 swap_32(&(p.attributes));
1751
1752#ifdef OLD_BUG
1753 swap_short(&(p.mark));
1754#else
1755 p.mark = *(swap_short(&(p.mark)));
1756#endif
1757 }
1758
1759 /* write the start marker
1760 */
1761 if (pushdata_isfirst == 1)
1762 {
1763 if (sh.flag.update == S_FALSE)
1764 {
1765 if (sh_db_version_string != NULL)
1766 {
1767 if (pushdata_stdout == S_FALSE)
1768 {
1769 sl_write (pushdata_fd, _("\n#Host "), 7);
1770 sl_write (pushdata_fd, sh.host.name,
1771 sl_strlen(sh.host.name));
1772 sl_write (pushdata_fd, _(" Version "), 9);
1773 sl_write (pushdata_fd, sh_db_version_string,
1774 sl_strlen(sh_db_version_string));
1775 sl_write (pushdata_fd, _(" Date "), 6);
1776 (void) sh_unix_time(0, timestring, sizeof(timestring));
1777 sl_write (pushdata_fd, timestring, sl_strlen(timestring));
1778 sl_write (pushdata_fd, "\n", 1);
1779 } else {
1780 printf (_("\n#Host "));
1781 printf ("%s", sh.host.name);
1782 printf (_(" Version "));
1783 printf ("%s", sh_db_version_string);
1784 printf (_(" Date "));
1785 (void) sh_unix_time(0, timestring, sizeof(timestring));
1786 printf ("%s\n", timestring);
1787 }
1788 }
1789
1790 if (pushdata_stdout == S_FALSE)
1791 {
1792#if defined(SH_STEALTH)
1793 sl_write (pushdata_fd, "\n", 1);
1794 sl_write_line (pushdata_fd, N_("[SOF]"), 5);
1795#else
1796 sl_write_line (pushdata_fd, _("\n[SOF]"), 6);
1797#endif
1798 }
1799 else
1800 {
1801#if defined(SH_STEALTH)
1802 printf ("\n%s\n", N_("[SOF]"));
1803#else
1804 printf ("%s\n", _("\n[SOF]"));
1805#endif
1806 }
1807 }
1808 pushdata_isfirst = 0;
1809 }
1810
1811 if (pushdata_stdout == S_FALSE)
1812 {
1813 sl_write (pushdata_fd, &p, sizeof(sh_filestore_t));
1814 sl_write_line_fast (pushdata_fd, fullpath, sl_strlen(fullpath));
1815 sl_write_line_fast (pushdata_fd, linkpath, sl_strlen(linkpath));
1816 if (attr_string)
1817 sl_write_line_fast (pushdata_fd, attr_string, sl_strlen(attr_string));
1818 } else {
1819 if (fwrite (&p, sizeof(sh_filestore_t), 1, stdout))
1820 {
1821 printf ("%s\n", fullpath);
1822 printf ("%s\n", linkpath);
1823 if (attr_string)
1824 printf ("%s\n", attr_string);
1825 }
1826 else
1827 {
1828 perror(_("Error writing database"));
1829 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1830 }
1831 }
1832
1833 ++p_count;
1834
1835 if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
1836 {
1837 if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
1838 {
1839 sl_close (pushdata_fd);
1840 pushdata_fd = -1;
1841 }
1842 }
1843
1844 SH_FREE(fullpath);
1845 SH_FREE(linkpath);
1846 if (attr_string)
1847 SH_FREE(attr_string);
1848
1849 SL_RET0(_("sh_hash_pushdata_int"));
1850}
1851
1852SH_MUTEX_STATIC(mutex_writeout,PTHREAD_MUTEX_INITIALIZER);
1853
1854void sh_hash_pushdata (file_type * buf, char * fileHash)
1855{
1856 SH_MUTEX_LOCK(mutex_writeout);
1857 sh_hash_pushdata_int (buf, fileHash);
1858 SH_MUTEX_UNLOCK(mutex_writeout);
1859 return;
1860}
1861
1862
1863int sh_hash_writeout()
1864{
1865 sh_file_t * p;
1866 int i;
1867 file_type * f;
1868 char fileHash[KEY_LEN + 1];
1869
1870 SL_ENTER(_("sh_hash_writeout"));
1871
1872 if (S_TRUE == file_is_remote())
1873 {
1874 sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN,
1875 _("Baseline database is remote"), _("sh_hash_writeout"));
1876 SL_RETURN (1, _("sh_hash_writeout"));
1877 }
1878
1879 SH_MUTEX_LOCK(mutex_writeout);
1880 if (!SL_ISERROR(pushdata_fd))
1881 {
1882 sl_close(pushdata_fd);
1883 pushdata_fd = -1;
1884 }
1885 pushdata_isfirst = 1;
1886
1887
1888 SH_MUTEX_LOCK(mutex_hash);
1889 for (i = 0; i < TABSIZE; ++i)
1890 {
1891 for (p = tab[i]; p; p = p->next)
1892 {
1893 f = sh_hash_create_ft (p, fileHash);
1894 sh_hash_pushdata_int (f, fileHash);
1895 if (f->attr_string) SH_FREE(f->attr_string);
1896 if (f->link_path) SH_FREE(f->link_path);
1897 SH_FREE(f);
1898 }
1899 }
1900 SH_MUTEX_UNLOCK(mutex_hash);
1901
1902 if (!SL_ISERROR(pushdata_fd))
1903 {
1904 sl_close(pushdata_fd);
1905 pushdata_fd = -1;
1906 }
1907 pushdata_isfirst = 1;
1908 SH_MUTEX_UNLOCK(mutex_writeout);
1909
1910 SL_RETURN (0, _("sh_hash_writeout"));
1911}
1912
1913
1914/*********************************************************************
1915 *
1916 * Check whether a file is present in the database.
1917 *
1918 *********************************************************************/
1919static sh_file_t * sh_hash_have_it_int (char * newname)
1920{
1921 sh_file_t * p;
1922 char hashbuf[KEYBUF_SIZE];
1923
1924 SL_ENTER(_("sh_hash_have_it_int"));
1925
1926 if (newname == NULL)
1927 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
1928
1929 if (sl_strlen(newname) <= MAX_PATH_STORE)
1930 p = hashsearch(newname);
1931 else
1932 p = hashsearch ( sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
1933 hashbuf, sizeof(hashbuf)) );
1934 if (p == NULL)
1935 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
1936
1937 SL_RETURN( (p), _("sh_hash_have_it_int"));
1938}
1939
1940int sh_hash_have_it (char * newname)
1941{
1942 sh_file_t * p;
1943 int retval;
1944
1945 if (IsInit != 1)
1946 sh_hash_init();
1947
1948 SH_MUTEX_LOCK(mutex_hash);
1949
1950 retval = 0;
1951
1952 p = sh_hash_have_it_int (newname);
1953
1954 if (!p)
1955 retval = (-1);
1956 else if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) &&
1957 (p->modi_mask & MODI_CHK) != 0 &&
1958 (p->modi_mask & MODI_MOD) != 0)
1959 retval = 1;
1960 SH_MUTEX_UNLOCK(mutex_hash);
1961
1962 return retval;
1963}
1964
1965int sh_hash_get_it (char * newname, file_type * tmpFile)
1966{
1967 sh_file_t * p;
1968 int retval;
1969
1970 if (IsInit != 1)
1971 sh_hash_init();
1972
1973 tmpFile->link_path = NULL;
1974 tmpFile->attr_string = NULL;
1975
1976 SH_MUTEX_LOCK(mutex_hash);
1977
1978 retval = (-1);
1979
1980 p = sh_hash_have_it_int (newname);
1981 if (p)
1982 {
1983 sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
1984 if (p->linkpath)
1985 tmpFile->link_path = sh_util_strdup (p->linkpath);
1986 tmpFile->size = p->theFile.size;
1987 tmpFile->mtime = p->theFile.mtime;
1988 tmpFile->ctime = p->theFile.ctime;
1989 tmpFile->attr_string = NULL;
1990 retval = 0;
1991 }
1992 SH_MUTEX_UNLOCK(mutex_hash);
1993
1994 return retval;
1995}
1996
1997int sh_hash_getflags (char * filename)
1998{
1999 sh_file_t * p;
2000 int retval;
2001
2002 if (IsInit != 1)
2003 sh_hash_init();
2004
2005 SH_MUTEX_LOCK(mutex_hash);
2006 p = sh_hash_have_it_int (filename);
2007 if (p)
2008 retval = p->fflags;
2009 else
2010 retval = -1;
2011 SH_MUTEX_UNLOCK(mutex_hash);
2012 return retval;
2013}
2014
2015int sh_hash_setflags (char * filename, int flags)
2016{
2017 sh_file_t * p;
2018 int retval;
2019
2020 if (IsInit != 1)
2021 sh_hash_init();
2022
2023 SH_MUTEX_LOCK(mutex_hash);
2024 p = sh_hash_have_it_int (filename);
2025 if (p)
2026 {
2027 p->fflags = flags;
2028 retval = 0;
2029 }
2030 else
2031 retval = -1;
2032 SH_MUTEX_UNLOCK(mutex_hash);
2033 return retval;
2034}
2035
2036/* needs lock to be threadsafe
2037 */
2038void sh_hash_addflag (char * filename, int flag_to_set)
2039{
2040 sh_file_t * p;
2041
2042 if (IsInit != 1)
2043 sh_hash_init();
2044
2045 SH_MUTEX_LOCK(mutex_hash);
2046 p = sh_hash_have_it_int (filename);
2047 if (p)
2048 {
2049 p->fflags |= flag_to_set;
2050 }
2051 SH_MUTEX_UNLOCK(mutex_hash);
2052 return;
2053}
2054
2055/*****************************************************************
2056 *
2057 * Set a file's status to 'visited'. This is required for
2058 * files that should be ignored, and may be present in the
2059 * database, but not on disk.
2060 *
2061 *****************************************************************/
2062static int sh_hash_set_visited_int (char * newname, int flag)
2063{
2064 sh_file_t * p;
2065 char hashbuf[KEYBUF_SIZE];
2066 int retval;
2067
2068 SL_ENTER(_("sh_hash_set_visited_int"));
2069
2070 if (newname == NULL)
2071 SL_RETURN((-1), _("sh_hash_set_visited_int"));
2072
2073 if (IsInit != 1)
2074 sh_hash_init();
2075
2076 SH_MUTEX_LOCK(mutex_hash);
2077
2078 if (sl_strlen(newname) <= MAX_PATH_STORE)
2079 p = hashsearch(newname);
2080 else
2081 p = hashsearch (sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
2082 hashbuf, sizeof(hashbuf)));
2083
2084 if (p)
2085 {
2086 if (flag == SH_FFLAG_CHECKED)
2087 {
2088 CLEAR_SH_FFLAG_REPORTED(p->fflags);
2089 CLEAR_SH_FFLAG_VISITED(p->fflags);
2090 SET_SH_FFLAG_CHECKED(p->fflags);
2091 }
2092 else
2093 {
2094 SET_SH_FFLAG_VISITED(p->fflags);
2095 CLEAR_SH_FFLAG_CHECKED(p->fflags);
2096 if (flag == SH_FFLAG_REPORTED)
2097 SET_SH_FFLAG_REPORTED(p->fflags);
2098 else
2099 CLEAR_SH_FFLAG_REPORTED(p->fflags);
2100 }
2101 retval = 0;
2102 }
2103 else
2104 retval = -1;
2105
2106 SH_MUTEX_UNLOCK(mutex_hash);
2107 SL_RETURN((retval), _("sh_hash_set_visited_int"));
2108}
2109
2110
2111/* cause the record to be deleted without a 'missing' message
2112 */
2113int sh_hash_set_missing (char * newname)
2114{
2115 int i;
2116 SL_ENTER(_("sh_hash_set_visited"));
2117 i = sh_hash_set_visited_int(newname, SH_FFLAG_CHECKED);
2118 SL_RETURN(i, _("sh_hash_set_visited"));
2119}
2120
2121/* mark the file as visited and reported
2122 */
2123int sh_hash_set_visited (char * newname)
2124{
2125 int i;
2126 SL_ENTER(_("sh_hash_set_visited"));
2127 i = sh_hash_set_visited_int(newname, SH_FFLAG_REPORTED);
2128 SL_RETURN(i, _("sh_hash_set_visited"));
2129}
2130
2131/* mark the file as visited and NOT reported
2132 * used to avoid deletion of file from internal database
2133 */
2134int sh_hash_set_visited_true (char * newname)
2135{
2136 int i;
2137 SL_ENTER(_("sh_hash_set_visited_true"));
2138 i = sh_hash_set_visited_int(newname, 0);
2139 SL_RETURN(i, _("sh_hash_set_visited_true"));
2140}
2141
2142
2143/******************************************************************
2144 *
2145 * Data entry for arbitrary data into database
2146 *
2147 ******************************************************************/
2148
2149void sh_hash_push2db (char * key, unsigned long val1,
2150 unsigned long val2, unsigned long val3,
2151 unsigned char * str, int size)
2152{
2153 file_type tmpFile;
2154 int i = 0;
2155 char * p;
2156 char i2h[2];
2157
2158 tmpFile.attr_string = NULL;
2159 tmpFile.link_path = NULL;
2160
2161 sl_strlcpy(tmpFile.fullpath, key, PATH_MAX);
2162 tmpFile.size = val1;
2163 tmpFile.mtime = val2;
2164 tmpFile.ctime = val3;
2165
2166 tmpFile.atime = 0;
2167 tmpFile.mode = 0;
2168 tmpFile.owner = 0;
2169 tmpFile.group = 0;
2170 sl_strlcpy(tmpFile.c_owner, _("root"), 5);
2171 sl_strlcpy(tmpFile.c_group, _("root"), 5);
2172
2173 if ((str != NULL) && (size < (PATH_MAX/2)-1))
2174 {
2175 tmpFile.c_mode[0] = 'l';
2176 tmpFile.c_mode[1] = 'r'; tmpFile.c_mode[2] = 'w';
2177 tmpFile.c_mode[3] = 'x'; tmpFile.c_mode[4] = 'r';
2178 tmpFile.c_mode[5] = 'w'; tmpFile.c_mode[6] = 'x';
2179 tmpFile.c_mode[7] = 'r'; tmpFile.c_mode[8] = 'w';
2180 tmpFile.c_mode[9] = 'x'; tmpFile.c_mode[10] = '\0';
2181 tmpFile.link_path = SH_ALLOC((size * 2) + 2);
2182 for (i = 0; i < size; ++i)
2183 {
2184 p = sh_util_charhex (str[i],i2h);
2185 tmpFile.link_path[2*i] = p[0];
2186 tmpFile.link_path[2*i+1] = p[1];
2187 tmpFile.link_path[2*i+2] = '\0';
2188 }
2189 }
2190 else
2191 {
2192 for (i = 0; i < 10; ++i)
2193 tmpFile.c_mode[i] = '-';
2194 tmpFile.c_mode[10] = '\0';
2195 tmpFile.link_path = sh_util_strdup("-");
2196 }
2197
2198 if (sh.flag.checkSum == SH_CHECK_CHECK &&
2199 sh.flag.update == S_TRUE)
2200 sh_hash_pushdata_memory (&tmpFile, SH_KEY_NULL);
2201 else
2202 sh_hash_pushdata (&tmpFile, SH_KEY_NULL);
2203
2204 if (tmpFile.link_path) SH_FREE(tmpFile.link_path);
2205 return;
2206}
2207
2208extern int sh_util_hextobinary (char * binary, char * hex, int bytes);
2209
2210char * sh_hash_db2pop (char * key, unsigned long * val1,
2211 unsigned long * val2, unsigned long * val3,
2212 int * size)
2213{
2214 file_type tmpFile;
2215 size_t len;
2216 char * p;
2217 int i;
2218 char * retval = NULL;
2219
2220 *size = 0;
2221
2222 if (0 == sh_hash_get_it (key, &tmpFile))
2223 {
2224 *val1 = tmpFile.size;
2225 *val2 = tmpFile.mtime;
2226 *val3 = tmpFile.ctime;
2227
2228 if (tmpFile.link_path && tmpFile.link_path[0] != '-')
2229 {
2230 len = strlen(tmpFile.link_path);
2231
2232 p = SH_ALLOC((len/2)+1);
2233 i = sh_util_hextobinary (p, tmpFile.link_path, len);
2234
2235 if (i == 0)
2236 {
2237 *size = (len/2);
2238 p[*size] = '\0';
2239 retval = p;
2240 }
2241 else
2242 {
2243 SH_FREE(p);
2244 *size = 0;
2245 }
2246 }
2247 else
2248 {
2249 *size = 0;
2250 }
2251 }
2252 else
2253 {
2254 *size = -1;
2255 *val1 = 0;
2256 *val2 = 0;
2257 *val3 = 0;
2258 }
2259 if (tmpFile.link_path) SH_FREE(tmpFile.link_path);
2260 return retval;
2261}
2262
2263
2264
2265
2266/******************************************************************
2267 *
2268 * Data entry in hash table
2269 *
2270 ******************************************************************/
2271sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
2272{
2273 sh_file_t * fp;
2274 sh_filestore_t p;
2275
2276 size_t len;
2277 char * fullpath;
2278 char * linkpath;
2279 char * attr_string = NULL;
2280 char hashbuf[KEYBUF_SIZE];
2281
2282 SL_ENTER(_("sh_hash_push_int"));
2283
2284 fp = SH_ALLOC(sizeof(sh_file_t));
2285
2286 p.mark = REC_MAGIC;
2287 if (buf->attr_string)
2288 p.mark |= REC_FLAGS_ATTR;
2289 sl_strlcpy(p.c_mode, buf->c_mode, 11);
2290 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
2291 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
2292 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
2293#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2294 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
2295#endif
2296
2297#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2298 p.attributes = (UINT32) buf->attributes;
2299#endif
2300 p.linkmode = (UINT32) buf->linkmode;
2301 p.hardlinks = (UINT32) buf->hardlinks;
2302 p.dev = (UINT64) buf->dev;
2303 p.rdev = (UINT64) buf->rdev;
2304 p.mode = (UINT32) buf->mode;
2305 p.ino = (UINT32) buf->ino;
2306 p.size = (UINT64) buf->size;
2307 p.mtime = (UINT64) buf->mtime;
2308 p.atime = (UINT64) buf->atime;
2309 p.ctime = (UINT64) buf->ctime;
2310 p.owner = (UINT32) buf->owner;
2311 p.group = (UINT32) buf->group;
2312
2313 memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
2314 fp->fflags = 0; /* init fflags */
2315 fp->modi_mask = 0L;
2316
2317 if (buf->attr_string)
2318 attr_string = sh_util_strdup(buf->attr_string);
2319 fp->attr_string = attr_string;
2320
2321 len = sl_strlen(buf->fullpath);
2322 if (len <= MAX_PATH_STORE)
2323 {
2324 fullpath = SH_ALLOC(len+1);
2325 sl_strlcpy(fullpath, buf->fullpath, len+1);
2326 }
2327 else
2328 {
2329 fullpath = SH_ALLOC(KEY_LEN + 1);
2330 sl_strlcpy(fullpath,
2331 sh_tiger_hash (buf->fullpath, TIGER_DATA, len,
2332 hashbuf, sizeof(hashbuf)),
2333 KEY_LEN+1);
2334 }
2335 fp->fullpath = fullpath;
2336
2337 if (buf->link_path)
2338 {
2339 len = sl_strlen(buf->link_path);
2340 if (len <= MAX_PATH_STORE)
2341 {
2342 linkpath = SH_ALLOC(len+1);
2343 sl_strlcpy(linkpath, buf->link_path, len+1);
2344 }
2345 else
2346 {
2347 linkpath = SH_ALLOC(KEY_LEN + 1);
2348 sl_strlcpy(linkpath,
2349 sh_tiger_hash (buf->link_path, TIGER_DATA, len,
2350 hashbuf, sizeof(hashbuf)),
2351 KEY_LEN+1);
2352 }
2353 fp->linkpath = linkpath;
2354 }
2355 else
2356 fp->linkpath = NULL;
2357
2358 SL_RETURN( fp, _("sh_hash_push_int"));
2359}
2360
2361#ifdef HAVE_INTTYPES_H
2362#include <inttypes.h>
2363#else
2364#ifdef HAVE_STDINT_H
2365#include <stdint.h>
2366#endif
2367#endif
2368
2369#ifndef PRIu64
2370#ifdef HAVE_LONG_32
2371#define PRIu64 "llu"
2372#else
2373#define PRIu64 "lu"
2374#endif
2375#endif
2376
2377char * sh_hash_size_format()
2378{
2379 static char form_rval[81];
2380
2381 SL_ENTER(_("sh_hash_size_format"));
2382
2383
2384#ifdef SH_USE_XML
2385 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2386 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
2387#else
2388 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2389 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
2390#endif
2391
2392 SL_RETURN( form_rval, _("sh_hash_size_format"));
2393}
2394
2395
2396#ifdef SH_USE_XML
2397static char * all_items (file_type * theFile, char * fileHash, int is_new)
2398{
2399 char timstr1c[32];
2400 char timstr1a[32];
2401 char timstr1m[32];
2402
2403 char * tmp_lnk;
2404 char * format;
2405
2406 char * tmp = SH_ALLOC(SH_MSG_BUF);
2407 char * msg = SH_ALLOC(SH_MSG_BUF);
2408
2409 tmp[0] = '\0';
2410 msg[0] = '\0';
2411
2412
2413#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2414 if (is_new)
2415 format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" ");
2416 else
2417 format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" ");
2418 sl_snprintf(tmp, SH_MSG_BUF, format,
2419 theFile->c_mode,
2420 theFile->c_attributes,
2421 (long) theFile->mode,
2422 (long) theFile->attributes
2423 );
2424#else
2425 if (is_new)
2426 format = _("mode_new=\"%s\" imode_new=\"%ld\" ");
2427 else
2428 format = _("mode_old=\"%s\" imode_old=\"%ld\" ");
2429
2430 sl_snprintf(tmp, SH_MSG_BUF, format,
2431 theFile->c_mode,
2432 (long) theFile->mode
2433 );
2434#endif
2435 sl_strlcat(msg, tmp, SH_MSG_BUF);
2436
2437 if (is_new)
2438 format = _("hardlinks_new=\"%lu\" ");
2439 else
2440 format = _("hardlinks_old=\"%lu\" ");
2441 sl_snprintf(tmp, SH_MSG_BUF, format,
2442 (unsigned long) theFile->hardlinks);
2443 sl_strlcat(msg, tmp, SH_MSG_BUF);
2444
2445
2446 if (is_new)
2447 format = _("idevice_new=\"%lu\" ");
2448 else
2449 format = _("idevice_old=\"%lu\" ");
2450 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2451 sl_strlcat(msg, tmp, SH_MSG_BUF);
2452
2453
2454 if (is_new)
2455 format = _("inode_new=\"%lu\" ");
2456 else
2457 format = _("inode_old=\"%lu\" ");
2458 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2459 sl_strlcat(msg, tmp, SH_MSG_BUF);
2460
2461 /*
2462 * also report device for prelude
2463 */
2464#if defined(HAVE_LIBPRELUDE)
2465 if (is_new)
2466 format = _("dev_new=\"%lu,%lu\" ");
2467 else
2468 format = _("dev_old=\"%lu,%lu\" ");
2469 sl_snprintf(tmp, SH_MSG_BUF, format,
2470 (unsigned long) major(theFile->dev),
2471 (unsigned long) minor(theFile->dev));
2472 sl_strlcat(msg, tmp, SH_MSG_BUF);
2473#endif
2474
2475
2476 if (is_new)
2477 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
2478 else
2479 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
2480 sl_snprintf(tmp, SH_MSG_BUF, format,
2481 theFile->c_owner, (long) theFile->owner);
2482 sl_strlcat(msg, tmp, SH_MSG_BUF);
2483
2484
2485 if (is_new)
2486 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
2487 else
2488 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
2489 sl_snprintf(tmp, SH_MSG_BUF, format,
2490 theFile->c_group, (long) theFile->group);
2491 sl_strlcat(msg, tmp, SH_MSG_BUF);
2492
2493
2494 if (is_new)
2495 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2496 (UINT64) 0, (UINT64) theFile->size);
2497 else
2498 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2499 (UINT64) theFile->size, (UINT64) 0);
2500 sl_strlcat(msg, tmp, SH_MSG_BUF);
2501
2502
2503 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2504 if (is_new)
2505 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=\"%s\" "), timstr1c);
2506 else
2507 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" "), timstr1c);
2508 sl_strlcat(msg, tmp, SH_MSG_BUF);
2509
2510 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2511 if (is_new)
2512 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=\"%s\" "), timstr1a);
2513 else
2514 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" "), timstr1a);
2515 sl_strlcat(msg, tmp, SH_MSG_BUF);
2516
2517 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2518 if (is_new)
2519 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=\"%s\" "), timstr1m);
2520 else
2521 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" "), timstr1m);
2522 sl_strlcat(msg, tmp, SH_MSG_BUF);
2523
2524 if (is_new)
2525 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=\"%s\" "), fileHash);
2526 else
2527 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=\"%s\" "), fileHash);
2528 sl_strlcat(msg, tmp, SH_MSG_BUF);
2529
2530 if (theFile->c_mode[0] == 'l' ||
2531 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
2532 {
2533 tmp_lnk = sh_util_safe_name(theFile->link_path);
2534 if (tmp_lnk)
2535 {
2536 if (is_new)
2537 sl_snprintf(tmp, SH_MSG_BUF, _("link_new=\"%s\" "), tmp_lnk);
2538 else
2539 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" "), tmp_lnk);
2540 SH_FREE(tmp_lnk);
2541 sl_strlcat(msg, tmp, SH_MSG_BUF);
2542 }
2543 }
2544
2545 if (theFile->attr_string)
2546 {
2547 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2548 if (tmp_lnk)
2549 {
2550 if (is_new)
2551 sl_snprintf(tmp, SH_MSG_BUF, _("acl_new=\"%s\" "), tmp_lnk);
2552 else
2553 sl_snprintf(tmp, SH_MSG_BUF, _("acl_old=\"%s\" "), tmp_lnk);
2554 SH_FREE(tmp_lnk);
2555 sl_strlcat(msg, tmp, SH_MSG_BUF);
2556 }
2557 }
2558
2559
2560 SH_FREE(tmp);
2561 return (msg);
2562}
2563#else
2564static char * all_items (file_type * theFile, char * fileHash, int is_new)
2565{
2566 char timstr1c[32];
2567 char timstr1a[32];
2568 char timstr1m[32];
2569
2570 char * tmp_lnk;
2571 char * format;
2572
2573 char * tmp = SH_ALLOC(SH_MSG_BUF);
2574 char * msg = SH_ALLOC(SH_MSG_BUF);
2575
2576 tmp[0] = '\0';
2577 msg[0] = '\0';
2578
2579
2580#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2581 if (is_new)
2582 format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, ");
2583 else
2584 format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, ");
2585 sl_snprintf(tmp, SH_MSG_BUF, format,
2586 theFile->c_mode,
2587 theFile->c_attributes,
2588 (long) theFile->mode,
2589 (long) theFile->attributes
2590 );
2591#else
2592 if (is_new)
2593 format = _("mode_new=<%s>, imode_new=<%ld>, ");
2594 else
2595 format = _("mode_old=<%s>, imode_old=<%ld>, ");
2596
2597 sl_snprintf(tmp, SH_MSG_BUF, format,
2598 theFile->c_mode,
2599 (long) theFile->mode
2600 );
2601#endif
2602 sl_strlcat(msg, tmp, SH_MSG_BUF);
2603
2604 if (is_new)
2605 format = _("hardlinks_new=<%lu>, ");
2606 else
2607 format = _("hardlinks_old=<%lu>, ");
2608 sl_snprintf(tmp, SH_MSG_BUF, format,
2609 (unsigned long) theFile->hardlinks);
2610 sl_strlcat(msg, tmp, SH_MSG_BUF);
2611
2612
2613 if (is_new)
2614 format = _("idevice_new=<%lu>, ");
2615 else
2616 format = _("idevice_old=<%lu>, ");
2617 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2618 sl_strlcat(msg, tmp, SH_MSG_BUF);
2619
2620
2621 if (is_new)
2622 format = _("inode_new=<%lu>, ");
2623 else
2624 format = _("inode_old=<%lu>, ");
2625 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2626 sl_strlcat(msg, tmp, SH_MSG_BUF);
2627
2628
2629 /*
2630 * also report device for prelude
2631 */
2632#if defined(HAVE_LIBPRELUDE)
2633 if (is_new)
2634 format = _("dev_new=<%lu,%lu>, ");
2635 else
2636 format = _("dev_old=<%lu,%lu>, ");
2637 sl_snprintf(tmp, SH_MSG_BUF, format,
2638 (unsigned long) major(theFile->dev),
2639 (unsigned long) minor(theFile->dev));
2640 sl_strlcat(msg, tmp, SH_MSG_BUF);
2641#endif
2642
2643 if (is_new)
2644 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
2645 else
2646 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
2647 sl_snprintf(tmp, SH_MSG_BUF, format,
2648 theFile->c_owner, (long) theFile->owner);
2649 sl_strlcat(msg, tmp, SH_MSG_BUF);
2650
2651
2652 if (is_new)
2653 format = _("group_new=<%s>, igroup_new=<%ld>, ");
2654 else
2655 format = _("group_old=<%s>, igroup_old=<%ld>, ");
2656 sl_snprintf(tmp, SH_MSG_BUF, format,
2657 theFile->c_group, (long) theFile->group);
2658 sl_strlcat(msg, tmp, SH_MSG_BUF);
2659
2660
2661 if (is_new)
2662 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2663 (UINT64) 0, (UINT64) theFile->size);
2664 else
2665 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2666 (UINT64) theFile->size, (UINT64) 0);
2667 sl_strlcat(msg, tmp, SH_MSG_BUF);
2668
2669
2670 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2671 if (is_new)
2672 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=<%s>, "), timstr1c);
2673 else
2674 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, "), timstr1c);
2675 sl_strlcat(msg, tmp, SH_MSG_BUF);
2676
2677 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2678 if (is_new)
2679 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=<%s>, "), timstr1a);
2680 else
2681 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, "), timstr1a);
2682 sl_strlcat(msg, tmp, SH_MSG_BUF);
2683
2684 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2685 if (is_new)
2686 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=<%s>, "), timstr1m);
2687 else
2688 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, "), timstr1m);
2689 sl_strlcat(msg, tmp, SH_MSG_BUF);
2690
2691 if (is_new)
2692 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=<%s>"), fileHash);
2693 else
2694 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=<%s>"), fileHash);
2695 sl_strlcat(msg, tmp, SH_MSG_BUF);
2696
2697 if (theFile->c_mode[0] == 'l' ||
2698 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
2699 {
2700 tmp_lnk = sh_util_safe_name(theFile->link_path);
2701 if (tmp_lnk)
2702 {
2703 if (is_new)
2704 sl_snprintf(tmp, SH_MSG_BUF, _(", link_new=<%s> "), tmp_lnk);
2705 else
2706 sl_snprintf(tmp, SH_MSG_BUF, _(", link_old=<%s> "), tmp_lnk);
2707 SH_FREE(tmp_lnk);
2708 sl_strlcat(msg, tmp, SH_MSG_BUF);
2709 }
2710 }
2711
2712 if (theFile->attr_string)
2713 {
2714 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2715 if (tmp_lnk)
2716 {
2717 if (is_new)
2718 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_new=<%s> "), tmp_lnk);
2719 else
2720 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_old=<%s> "), tmp_lnk);
2721 SH_FREE(tmp_lnk);
2722 sl_strlcat(msg, tmp, SH_MSG_BUF);
2723 }
2724 }
2725
2726 SH_FREE(tmp);
2727 return (msg);
2728}
2729#endif
2730
2731void sh_hash_pushdata_memory (file_type * theFile, char * fileHash)
2732{
2733 sh_file_t * p;
2734
2735 SL_ENTER(_("sh_hash_pushdata_memory"));
2736
2737 p = sh_hash_push_int(theFile, fileHash);
2738 if (p)
2739 {
2740 SH_MUTEX_LOCK(mutex_hash);
2741 hashinsert (p);
2742 p->modi_mask = theFile->check_mask;
2743 SH_MUTEX_UNLOCK(mutex_hash);
2744 }
2745
2746 SL_RET0(_("sh_hash_pushdata_memory"));
2747}
2748
2749
2750/*****************************************************************
2751 *
2752 * Compare a file with the database status.
2753 *
2754 *****************************************************************/
2755int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
2756 char * policy_override, int severity_override)
2757{
2758 char * msg;
2759 sh_file_t * p;
2760 char * tmp;
2761 char * tmp_path;
2762 char * tmp_lnk;
2763 char * tmp_lnk_old;
2764
2765 char * str;
2766
2767 char timstr1c[32];
2768 char timstr2c[32];
2769 char timstr1a[32];
2770 char timstr2a[32];
2771 char timstr1m[32];
2772 char timstr2m[32];
2773 char linkHash[KEY_LEN+1];
2774 char * linkComp;
2775 int maxcomp;
2776
2777 char change_code[16];
2778 int i;
2779
2780 unsigned long modi_mask;
2781
2782 char log_policy[32];
2783 volatile int log_severity;
2784 char hashbuf[KEYBUF_SIZE];
2785
2786 int retval;
2787
2788 SL_ENTER(_("sh_hash_compdata"));
2789
2790 if (IsInit != 1) sh_hash_init();
2791
2792 if (severity_override < 0)
2793 log_severity = ShDFLevel[class];
2794 else
2795 log_severity = severity_override;
2796
2797 if (policy_override != NULL)
2798 sl_strlcpy (log_policy, policy_override, 32);
2799
2800 /* -------- find the entry for the file ---------------- */
2801
2802 SH_MUTEX_LOCK(mutex_hash);
2803
2804 modi_mask = 0;
2805 retval = 0;
2806
2807 if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE)
2808 p = hashsearch(theFile->fullpath);
2809 else
2810 p = hashsearch( sh_tiger_hash(theFile->fullpath,
2811 TIGER_DATA,
2812 sl_strlen(theFile->fullpath),
2813 hashbuf, sizeof(hashbuf))
2814 );
2815
2816
2817 /* --------- Not found in database. ------------
2818 */
2819
2820 if (p == NULL)
2821 {
2822 if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
2823 {
2824 tmp = sh_util_safe_name(theFile->fullpath);
2825
2826 str = all_items (theFile, fileHash, 1);
2827 sh_error_handle (log_severity, FIL__, __LINE__, 0,
2828 MSG_FI_ADD2,
2829 tmp, str);
2830 SH_FREE(str);
2831
2832 SH_FREE(tmp);
2833 }
2834
2835 if (sh.flag.reportonce == S_TRUE)
2836 SET_SH_FFLAG_REPORTED(theFile->file_reported);
2837
2838 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2839 {
2840 p = sh_hash_push_int(theFile, fileHash);
2841 if (p)
2842 {
2843 hashinsert (p);
2844 p->modi_mask = theFile->check_mask;
2845 }
2846 }
2847
2848 else if (S_TRUE == sh.flag.update)
2849 {
2850 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
2851 {
2852 p = sh_hash_push_int(theFile, fileHash);
2853 if (p)
2854 {
2855 hashinsert (p);
2856 p->modi_mask = theFile->check_mask;
2857 }
2858 }
2859 else
2860 {
2861 retval = 1;
2862 goto unlock_and_return;
2863 }
2864 }
2865
2866 goto unlock_and_return;
2867 }
2868
2869 p->modi_mask = theFile->check_mask;
2870
2871 /* initialize change_code */
2872 for (i = 0; i < 15; ++i)
2873 change_code[i] = '-';
2874 change_code[15] = '\0';
2875
2876 TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"),
2877 theFile->fullpath, fileHash, p->theFile.checksum));
2878
2879 if ( (fileHash != NULL) && (p->theFile.checksum != NULL) &&
2880 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
2881 (theFile->check_mask & MODI_CHK) != 0)
2882 {
2883 if ((theFile->check_mask & MODI_SGROW) == 0)
2884 {
2885 modi_mask |= MODI_CHK;
2886 change_code[0] = 'C';
2887 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
2888 }
2889 else
2890 {
2891 if (0 != strncmp (&fileHash[KEY_LEN + 1],
2892 p->theFile.checksum, KEY_LEN))
2893 {
2894 modi_mask |= MODI_CHK;
2895 change_code[0] = 'C';
2896 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
2897 }
2898 else
2899 {
2900 p->theFile.size = theFile->size;
2901 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2902 }
2903 }
2904 }
2905
2906 if (p->theFile.c_mode[0] == 'l')
2907 {
2908 if (!(theFile->link_path) &&
2909 (theFile->check_mask & MODI_LNK) != 0)
2910 {
2911 linkComp = NULL;
2912 modi_mask |= MODI_LNK;
2913 change_code[1] = 'L';
2914 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2915 }
2916 else
2917 {
2918 if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE)
2919 {
2920 sl_strlcpy(linkHash,
2921 sh_tiger_hash(theFile->link_path,
2922 TIGER_DATA,
2923 sl_strlen(theFile->link_path),
2924 hashbuf, sizeof(hashbuf)),
2925 MAX_PATH_STORE+1);
2926 linkComp = linkHash;
2927 maxcomp = KEY_LEN;
2928 }
2929 else
2930 {
2931 linkComp = theFile->link_path;
2932 maxcomp = MAX_PATH_STORE;
2933 }
2934
2935 if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 &&
2936 (theFile->check_mask & MODI_LNK) != 0)
2937 {
2938 modi_mask |= MODI_LNK;
2939 change_code[1] = 'L';
2940 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2941 }
2942 }
2943 }
2944
2945 if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b')
2946 {
2947 if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) ||
2948 minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
2949 (theFile->check_mask & MODI_RDEV) != 0)
2950 {
2951 modi_mask |= MODI_RDEV;
2952 change_code[2] = 'D';
2953 TPT ((0, FIL__, __LINE__, _("mod=<rdev>")));
2954 }
2955 }
2956
2957 /* cast to UINT32 in case ino_t is not 32bit
2958 */
2959 if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino &&
2960 (theFile->check_mask & MODI_INO) != 0)
2961 {
2962 modi_mask |= MODI_INO;
2963 change_code[3] = 'I';
2964 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2965 }
2966
2967 if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
2968 (theFile->check_mask & MODI_HLN) != 0)
2969 {
2970 modi_mask |= MODI_HLN;
2971 change_code[4] = 'H';
2972 TPT ((0, FIL__, __LINE__, _("mod=<hardlink>")));
2973 }
2974
2975
2976 if ( ( (theFile->mode != p->theFile.mode)
2977#if defined(USE_ACL) || defined(USE_XATTR)
2978 || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
2979 (
2980 (theFile->attr_string == NULL && p->attr_string != NULL) ||
2981 (theFile->attr_string != NULL && p->attr_string == NULL) ||
2982 (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
2983 )
2984 )
2985#endif
2986#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2987 || (theFile->attributes != p->theFile.attributes)
2988#endif
2989 )
2990 && (theFile->check_mask & MODI_MOD) != 0)
2991 {
2992 modi_mask |= MODI_MOD;
2993 change_code[5] = 'M';
2994 TPT ((0, FIL__, __LINE__, _("mod=<mode>")));
2995 /*
2996 * report link path if switch link/no link
2997 */
2998 if ((theFile->check_mask & MODI_LNK) != 0 &&
2999 (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
3000 (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
3001 {
3002 modi_mask |= MODI_LNK;
3003 change_code[1] = 'L';
3004 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
3005 }
3006 }
3007
3008 if ( theFile->owner != (uid_t) p->theFile.owner &&
3009 (theFile->check_mask & MODI_USR) != 0)
3010 {
3011 modi_mask |= MODI_USR;
3012 change_code[6] = 'U';
3013 TPT ((0, FIL__, __LINE__, _("mod=<user>")));
3014 }
3015
3016 if ( theFile->group != (gid_t) p->theFile.group &&
3017 (theFile->check_mask & MODI_GRP) != 0)
3018 {
3019 modi_mask |= MODI_GRP;
3020 change_code[7] = 'G';
3021 TPT ((0, FIL__, __LINE__, _("mod=<group>")));
3022 }
3023
3024
3025 if ( theFile->mtime != (time_t) p->theFile.mtime &&
3026 (theFile->check_mask & MODI_MTM) != 0)
3027 {
3028 modi_mask |= MODI_MTM;
3029 change_code[8] = 'T';
3030 TPT ((0, FIL__, __LINE__, _("mod=<mtime>")));
3031 }
3032
3033 if ( (theFile->check_mask & MODI_ATM) != 0 &&
3034 theFile->atime != (time_t) p->theFile.atime)
3035 {
3036 modi_mask |= MODI_ATM;
3037 change_code[8] = 'T';
3038 TPT ((0, FIL__, __LINE__, _("mod=<atime>")));
3039 }
3040
3041
3042 /* Resetting the access time will set a new ctime. Thus, either we ignore
3043 * the access time or the ctime for NOIGNORE
3044 */
3045 if ( theFile->ctime != (time_t) p->theFile.ctime &&
3046 (theFile->check_mask & MODI_CTM) != 0)
3047 {
3048 modi_mask |= MODI_CTM;
3049 change_code[8] = 'T';
3050 TPT ((0, FIL__, __LINE__, _("mod=<ctime>")));
3051 }
3052
3053 if ( theFile->size != (off_t) p->theFile.size &&
3054 (theFile->check_mask & MODI_SIZ) != 0)
3055 {
3056 if ((theFile->check_mask & MODI_SGROW) == 0 ||
3057 theFile->size < (off_t) p->theFile.size)
3058 {
3059 modi_mask |= MODI_SIZ;
3060 change_code[9] = 'S';
3061 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
3062 }
3063 }
3064 change_code[10] = '\0';
3065
3066 /* --- Directories special case ---
3067 */
3068 if (p->theFile.c_mode[0] == 'd' &&
3069 0 == (modi_mask & ~(MODI_SIZ|MODI_ATM|MODI_CTM|MODI_MTM)) &&
3070 sh_loosedircheck == S_TRUE)
3071 {
3072 modi_mask = 0;
3073 }
3074
3075 /* --- Report full details. ---
3076 */
3077 if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
3078 {
3079 if ((theFile->check_mask & MODI_ATM) == 0)
3080 modi_mask = MASK_READONLY_;
3081 else
3082 modi_mask = MASK_NOIGNORE_;
3083 }
3084
3085 /* --- Report on modified files. ---
3086 */
3087 if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
3088 {
3089 tmp = SH_ALLOC(SH_MSG_BUF);
3090 msg = SH_ALLOC(SH_MSG_BUF);
3091 msg[0] = '\0';
3092
3093 if ( ((modi_mask & MODI_MOD) != 0)
3094#if defined(HAVE_LIBPRELUDE)
3095 || ((modi_mask & MODI_USR) != 0)
3096 || ((modi_mask & MODI_GRP) != 0)
3097#endif
3098 )
3099 {
3100#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3101 sl_snprintf(tmp, SH_MSG_BUF,
3102#ifdef SH_USE_XML
3103 _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "),
3104#else
3105 _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "),
3106#endif
3107 p->theFile.c_mode, theFile->c_mode,
3108 p->theFile.c_attributes, theFile->c_attributes
3109#ifdef SH_USE_XML
3110 , (long) p->theFile.mode, (long) theFile->mode,
3111 (long) p->theFile.attributes,
3112 (long) theFile->attributes
3113#endif
3114 );
3115#else
3116#ifdef SH_USE_XML
3117 sl_snprintf(tmp, SH_MSG_BUF,
3118 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
3119 p->theFile.c_mode, theFile->c_mode,
3120 (long) p->theFile.mode, (long) theFile->mode);
3121#else
3122 sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=<%s>, mode_new=<%s>, "),
3123 p->theFile.c_mode, theFile->c_mode);
3124#endif
3125#endif
3126 sl_strlcat(msg, tmp, SH_MSG_BUF);
3127
3128#if defined(USE_ACL) || defined(USE_XATTR)
3129 if (theFile->attr_string != NULL || p->attr_string != NULL)
3130 {
3131 sl_snprintf(tmp, SH_MSG_BUF,
3132#ifdef SH_USE_XML
3133 _("acl_old=\"%s\" acl_new=\"%s\" "),
3134#else
3135 _("acl_old=<%s>, acl_new=<%s>, "),
3136#endif
3137 (p->attr_string) ? p->attr_string : _("none"),
3138 (theFile->attr_string) ? theFile->attr_string : _("none"));
3139
3140 sl_strlcat(msg, tmp, SH_MSG_BUF);
3141 }
3142#endif
3143
3144#ifdef REPLACE_OLD
3145 if ((modi_mask & MODI_MOD) != 0)
3146 {
3147 /*
3148 * We postpone update if sh.flag.update == S_TRUE because
3149 * in interactive mode the user may not accept the change.
3150 */
3151 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3152 {
3153 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3154 p->theFile.mode = theFile->mode;
3155#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3156 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
3157 p->theFile.attributes = theFile->attributes;
3158#endif
3159#if defined(USE_ACL) || defined(USE_XATTR)
3160 if (p->attr_string == NULL && theFile->attr_string != NULL)
3161 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3162 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3163 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3164 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3165 {
3166 if (0 != strcmp(theFile->attr_string, p->attr_string))
3167 {
3168 SH_FREE(p->attr_string);
3169 p->attr_string = sh_util_strdup (theFile->attr_string);
3170 }
3171 }
3172#endif
3173 }
3174 }
3175#endif
3176 }
3177
3178 if ((modi_mask & MODI_HLN) != 0)
3179 {
3180 sl_snprintf(tmp, SH_MSG_BUF,
3181#ifdef SH_USE_XML
3182 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
3183#else
3184 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
3185#endif
3186 (unsigned long) p->theFile.hardlinks,
3187 (unsigned long) theFile->hardlinks);
3188 sl_strlcat(msg, tmp, SH_MSG_BUF);
3189#ifdef REPLACE_OLD
3190 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3191 p->theFile.hardlinks = theFile->hardlinks;
3192#endif
3193 }
3194
3195 if ((modi_mask & MODI_RDEV) != 0)
3196 {
3197 sl_snprintf(tmp, SH_MSG_BUF,
3198#ifdef SH_USE_XML
3199 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
3200#else
3201 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
3202#endif
3203 (unsigned long) major(p->theFile.rdev),
3204 (unsigned long) minor(p->theFile.rdev),
3205 (unsigned long) major(theFile->rdev),
3206 (unsigned long) minor(theFile->rdev)
3207#ifdef SH_USE_XML
3208 , (unsigned long) p->theFile.rdev,
3209 (unsigned long) theFile->rdev
3210#endif
3211 );
3212 sl_strlcat(msg, tmp, SH_MSG_BUF);
3213#ifdef REPLACE_OLD
3214 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3215 p->theFile.rdev = theFile->rdev;
3216#endif
3217 }
3218
3219 if ((modi_mask & MODI_INO) != 0)
3220 {
3221 sl_snprintf(tmp, SH_MSG_BUF,
3222#ifdef SH_USE_XML
3223 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
3224#else
3225 _("inode_old=<%lu>, inode_new=<%lu>, "),
3226#endif
3227 (unsigned long) p->theFile.ino,
3228 (unsigned long) theFile->ino);
3229 sl_strlcat(msg, tmp, SH_MSG_BUF);
3230#ifdef REPLACE_OLD
3231 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3232 {
3233 p->theFile.ino = theFile->ino;
3234 p->theFile.dev = theFile->dev;
3235 }
3236#endif
3237 }
3238
3239
3240 /*
3241 * also report device for prelude
3242 */
3243#if defined(HAVE_LIBPRELUDE)
3244 if ((modi_mask & MODI_INO) != 0)
3245 {
3246 sl_snprintf(tmp, SH_MSG_BUF,
3247#ifdef SH_USE_XML
3248 _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "),
3249#else
3250 _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "),
3251#endif
3252 (unsigned long) major(p->theFile.dev),
3253 (unsigned long) minor(p->theFile.dev),
3254 (unsigned long) major(theFile->dev),
3255 (unsigned long) minor(theFile->dev)
3256 );
3257 sl_strlcat(msg, tmp, SH_MSG_BUF);
3258#ifdef REPLACE_OLD
3259 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3260 p->theFile.dev = theFile->dev;
3261#endif
3262 }
3263#endif
3264
3265 if ( ((modi_mask & MODI_USR) != 0)
3266#if defined(HAVE_LIBPRELUDE)
3267 || ((modi_mask & MODI_MOD) != 0)
3268#endif
3269 )
3270 {
3271#ifdef SH_USE_XML
3272 sl_snprintf(tmp, SH_MSG_BUF,
3273 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
3274#else
3275 sl_snprintf(tmp, SH_MSG_BUF,
3276 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
3277#endif
3278 p->theFile.c_owner, theFile->c_owner,
3279 (long) p->theFile.owner, (long) theFile->owner
3280 );
3281 sl_strlcat(msg, tmp, SH_MSG_BUF);
3282#ifdef REPLACE_OLD
3283 if ((modi_mask & MODI_USR) != 0) {
3284 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3285 {
3286 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3287 p->theFile.owner = theFile->owner;
3288 }
3289 }
3290#endif
3291 }
3292
3293 if ( ((modi_mask & MODI_GRP) != 0)
3294#if defined(HAVE_LIBPRELUDE)
3295 || ((modi_mask & MODI_MOD) != 0)
3296#endif
3297 )
3298 {
3299#ifdef SH_USE_XML
3300 sl_snprintf(tmp, SH_MSG_BUF,
3301 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
3302 p->theFile.c_group, theFile->c_group,
3303 (long) p->theFile.group, (long) theFile->group);
3304#else
3305 sl_snprintf(tmp, SH_MSG_BUF,
3306 _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "),
3307 p->theFile.c_group, theFile->c_group,
3308 (long) p->theFile.group, (long) theFile->group);
3309#endif
3310
3311 sl_strlcat(msg, tmp, SH_MSG_BUF);
3312#ifdef REPLACE_OLD
3313 if ((modi_mask & MODI_GRP) != 0) {
3314 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3315 {
3316 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3317 p->theFile.group = theFile->group;
3318 }
3319 }
3320#endif
3321 }
3322
3323 if ((modi_mask & MODI_SIZ) != 0)
3324 {
3325 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
3326 (UINT64) p->theFile.size,
3327 (UINT64) theFile->size);
3328 sl_strlcat(msg, tmp, SH_MSG_BUF);
3329#ifdef REPLACE_OLD
3330 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3331 p->theFile.size = theFile->size;
3332#endif
3333 }
3334
3335 if ((modi_mask & MODI_CTM) != 0)
3336 {
3337 (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c));
3338 (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c));
3339#ifdef SH_USE_XML
3340 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
3341 timstr1c, timstr2c);
3342#else
3343 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, ctime_new=<%s>, "),
3344 timstr1c, timstr2c);
3345#endif
3346 sl_strlcat(msg, tmp, SH_MSG_BUF);
3347#ifdef REPLACE_OLD
3348 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3349 p->theFile.ctime = theFile->ctime;
3350#endif
3351 }
3352
3353 if ((modi_mask & MODI_ATM) != 0)
3354 {
3355 (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a));
3356 (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a));
3357#ifdef SH_USE_XML
3358 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" atime_new=\"%s\" "),
3359 timstr1a, timstr2a);
3360#else
3361 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, atime_new=<%s>, "),
3362 timstr1a, timstr2a);
3363#endif
3364 sl_strlcat(msg, tmp, SH_MSG_BUF);
3365#ifdef REPLACE_OLD
3366 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3367 p->theFile.atime = theFile->atime;
3368#endif
3369 }
3370
3371 if ((modi_mask & MODI_MTM) != 0)
3372 {
3373 (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m));
3374 (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m));
3375#ifdef SH_USE_XML
3376 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
3377 timstr1m, timstr2m);
3378#else
3379 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, mtime_new=<%s>, "),
3380 timstr1m, timstr2m);
3381#endif
3382 sl_strlcat(msg, tmp, SH_MSG_BUF);
3383#ifdef REPLACE_OLD
3384 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3385 p->theFile.mtime = theFile->mtime;
3386#endif
3387 }
3388
3389
3390 if ((modi_mask & MODI_CHK) != 0)
3391 {
3392 sl_snprintf(tmp, SH_MSG_BUF,
3393#ifdef SH_USE_XML
3394 _("chksum_old=\"%s\" chksum_new=\"%s\" "),
3395#else
3396 _("chksum_old=<%s>, chksum_new=<%s>, "),
3397#endif
3398 p->theFile.checksum, fileHash);
3399 sl_strlcat(msg, tmp, SH_MSG_BUF);
3400#ifdef REPLACE_OLD
3401 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3402 {
3403 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3404 if ((theFile->check_mask & MODI_SGROW) != 0)
3405 p->theFile.size = theFile->size;
3406 }
3407#endif
3408 /* FIXME is this correct? */
3409 if (theFile->c_mode[0] != 'l' && theFile->link_path &&
3410 strlen(theFile->link_path) > 2)
3411 modi_mask |= MODI_LNK;
3412 }
3413
3414
3415 if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */)
3416 {
3417 if (theFile->link_path)
3418 tmp_lnk = sh_util_safe_name(theFile->link_path);
3419 else
3420 tmp_lnk = sh_util_strdup("-");
3421 if (p->linkpath)
3422 tmp_lnk_old = sh_util_safe_name(p->linkpath);
3423 else
3424 tmp_lnk_old = sh_util_strdup("-");
3425#ifdef SH_USE_XML
3426 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" link_new=\"%s\" "),
3427 tmp_lnk_old, tmp_lnk);
3428#else
3429 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=<%s>, link_new=<%s>"),
3430 tmp_lnk_old, tmp_lnk);
3431#endif
3432 SH_FREE(tmp_lnk);
3433 SH_FREE(tmp_lnk_old);
3434 sl_strlcat(msg, tmp, SH_MSG_BUF);
3435#ifdef REPLACE_OLD
3436 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3437 {
3438 if (p->linkpath != NULL && p->linkpath != notalink)
3439 SH_FREE(p->linkpath);
3440 if (!(theFile->link_path) ||
3441 (theFile->link_path[0] == '-' && theFile->link_path[1] == '\0'))
3442 p->linkpath = (char *)notalink;
3443 else
3444 p->linkpath = sh_util_strdup(theFile->link_path);
3445 }
3446#endif
3447 }
3448
3449
3450 tmp_path = sh_util_safe_name(theFile->fullpath);
3451 sh_error_handle(log_severity, FIL__, __LINE__,
3452 (long) modi_mask, MSG_FI_CHAN,
3453 (policy_override == NULL) ? _(policy[class]):log_policy,
3454 change_code, tmp_path, msg);
3455
3456 SH_FREE(tmp_path);
3457 SH_FREE(tmp);
3458 SH_FREE(msg);
3459
3460#ifndef REPLACE_OLD
3461 SET_SH_FFLAG_REPORTED(p->fflags);
3462#endif
3463
3464 if (S_TRUE == sh.flag.update)
3465 {
3466 if (S_FALSE == sh_util_ask_update(theFile->fullpath))
3467 {
3468 /* user does not want to update, thus we replace
3469 * with data from the baseline database
3470 */
3471 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
3472 theFile->mode = p->theFile.mode;
3473#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3474 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
3475 theFile->attributes = p->theFile.attributes;
3476#endif
3477#if defined(USE_ACL) || defined(USE_XATTR)
3478 if (theFile->attr_string == NULL && p->attr_string != NULL)
3479 { theFile->attr_string = sh_util_strdup (p->attr_string); }
3480 else if (theFile->attr_string != NULL && p->attr_string == NULL)
3481 { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
3482 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3483 {
3484 if (0 != strcmp(theFile->attr_string, p->attr_string))
3485 {
3486 SH_FREE(theFile->attr_string);
3487 theFile->attr_string = sh_util_strdup (p->attr_string);
3488 }
3489 }
3490#endif
3491
3492 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
3493 {
3494 if (theFile->link_path)
3495 SH_FREE(theFile->link_path);
3496 if (p->linkpath)
3497 theFile->link_path = sh_util_strdup(p->linkpath);
3498 else
3499 theFile->link_path = sh_util_strdup("-");
3500 }
3501 else
3502 {
3503 if (theFile->link_path)
3504 SH_FREE(theFile->link_path);
3505 if (p->linkpath && p->linkpath != notalink)
3506 theFile->link_path = sh_util_strdup(p->linkpath);
3507 else
3508 theFile->link_path = NULL;
3509 }
3510
3511 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
3512
3513 theFile->mtime = p->theFile.mtime;
3514 theFile->ctime = p->theFile.ctime;
3515 theFile->atime = p->theFile.atime;
3516
3517 theFile->size = p->theFile.size;
3518
3519 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
3520 theFile->group = p->theFile.group;
3521 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
3522 theFile->owner = p->theFile.owner;
3523
3524 theFile->ino = p->theFile.ino;
3525 theFile->rdev = p->theFile.rdev;
3526 theFile->dev = p->theFile.dev;
3527 theFile->hardlinks = p->theFile.hardlinks;
3528
3529 SET_SH_FFLAG_VISITED(p->fflags);
3530 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3531 retval = 1;
3532 goto unlock_and_return;
3533 }
3534 else /* if (sh.flag.reportonce == S_TRUE) */
3535 {
3536 /* we replace the data in the in-memory copy of the
3537 * baseline database, because otherwise we would get
3538 * another warning if the suidcheck runs
3539 */
3540 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3541 p->theFile.mode = theFile->mode;
3542#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3543 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
3544 p->theFile.attributes = theFile->attributes;
3545#endif
3546#if defined(USE_ACL) || defined(USE_XATTR)
3547 if (p->attr_string == NULL && theFile->attr_string != NULL)
3548 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3549 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3550 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3551 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3552 {
3553 if (0 != strcmp(theFile->attr_string, p->attr_string))
3554 {
3555 SH_FREE(p->attr_string);
3556 p->attr_string = sh_util_strdup (theFile->attr_string);
3557 }
3558 }
3559#endif
3560
3561 if (theFile->c_mode[0] == 'l' || theFile->link_path)
3562 {
3563 if (p->linkpath != NULL && p->linkpath != notalink)
3564 SH_FREE(p->linkpath);
3565 p->linkpath = sh_util_strdup(theFile->link_path);
3566 }
3567 else
3568 {
3569 if (p->linkpath != NULL && p->linkpath != notalink) {
3570 SH_FREE(p->linkpath);
3571 }
3572 p->linkpath = (char *)notalink;
3573 }
3574
3575 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3576
3577 p->theFile.mtime = theFile->mtime;
3578 p->theFile.ctime = theFile->ctime;
3579 p->theFile.atime = theFile->atime;
3580
3581 p->theFile.size = theFile->size;
3582
3583 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3584 p->theFile.group = theFile->group;
3585 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3586 p->theFile.owner = theFile->owner;
3587
3588 p->theFile.ino = theFile->ino;
3589 p->theFile.rdev = theFile->rdev;
3590 p->theFile.dev = theFile->dev;
3591 p->theFile.hardlinks = theFile->hardlinks;
3592 }
3593 }
3594 }
3595
3596 SET_SH_FFLAG_VISITED(p->fflags);
3597 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3598
3599 unlock_and_return:
3600 ; /* 'label at end of compound statement */
3601 SH_MUTEX_UNLOCK(mutex_hash);
3602 SL_RETURN(retval, _("sh_hash_compdata"));
3603}
3604
3605int hash_full_tree ()
3606{
3607 sh_file_t * p;
3608 int i;
3609
3610 SL_ENTER(_("sh_hash_compdata"));
3611
3612 if (IsInit != 1)
3613 SL_RETURN(0, _("sh_hash_compdata"));
3614
3615 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
3616 for (i = 0; i < TABSIZE; ++i)
3617 {
3618 for (p = tab[i]; p; p = p->next)
3619 CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
3620 }
3621 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
3622 SL_RETURN (0, _("sh_hash_compdata"));
3623}
3624
3625
3626int hash_remove_tree (char * s)
3627{
3628 sh_file_t * p;
3629 size_t len;
3630 unsigned int i;
3631
3632 SL_ENTER(_("hash_remove_tree"));
3633
3634 if (!s || *s == '\0')
3635 SL_RETURN ((-1), _("hash_remove_tree"));
3636
3637 len = sl_strlen(s);
3638
3639 if (IsInit != 1)
3640 sh_hash_init();
3641
3642 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
3643 for (i = 0; i < TABSIZE; ++i)
3644 {
3645 for (p = tab[i]; p; p = p->next)
3646 {
3647 if (p->fullpath && 0 == strncmp(s, p->fullpath, len))
3648 {
3649 SET_SH_FFLAG_ALLIGNORE(p->fflags);
3650 }
3651 }
3652 }
3653 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
3654 SL_RETURN ((0), _("hash_remove_tree"));
3655}
3656
3657#if TIME_WITH_SYS_TIME
3658#include <sys/time.h>
3659#include <time.h>
3660#else
3661#if HAVE_SYS_TIME_H
3662#include <sys/time.h>
3663#else
3664#include <time.h>
3665#endif
3666#endif
3667
3668static int ListFullDetail = S_FALSE;
3669static int ListWithDelimiter = S_FALSE;
3670static char * ListFile = NULL;
3671
3672int set_list_file (const char * c)
3673{
3674 ListFile = sh_util_strdup(c);
3675 return 0;
3676}
3677
3678int set_full_detail (const char * c)
3679{
3680 (void) c;
3681 ListFullDetail = S_TRUE;
3682 return 0;
3683}
3684
3685int set_list_delimited (const char * c)
3686{
3687 (void) c;
3688 ListFullDetail = S_TRUE;
3689 ListWithDelimiter = S_TRUE;
3690 return 0;
3691}
3692
3693/* Always quote the string, except if it is empty. Quote quotes by
3694 * doubling them.
3695 */
3696char * csv_escape(const char * str)
3697{
3698 const char * p = str;
3699 const char * q;
3700
3701 size_t size = 0;
3702 size_t flag_quote = 0;
3703 int flag_comma = 0;
3704 char * new;
3705 char * pnew;
3706
3707 if (p)
3708 {
3709
3710 while (*p)
3711 {
3712 if (*p == ',')
3713 flag_comma = 1;
3714 else if (*p == '"')
3715 ++flag_quote;
3716
3717 ++size; ++p;
3718 }
3719
3720 if (sl_ok_adds(size, flag_quote))
3721 size += flag_quote; /* double each quote */
3722 else
3723 return NULL;
3724
3725 if (sl_ok_adds(size, 3))
3726 size += 3; /* two quotes and terminating null */
3727 else
3728 return NULL;
3729
3730 new = SH_ALLOC(size);
3731
3732 if (flag_quote != 0)
3733 {
3734 new[0] = '"';
3735 pnew = &new[1];
3736 q = str;
3737 while (*q)
3738 {
3739 *pnew = *q;
3740 if (*pnew == '"')
3741 {
3742 ++pnew; *pnew = '"';
3743 }
3744 ++pnew; ++q;
3745 }
3746 *pnew = '"'; ++pnew;
3747 *pnew = '\0';
3748 }
3749 else
3750 {
3751 if (size > 3)
3752 {
3753 new[0] = '"';
3754 sl_strlcpy (&new[1], str, size-1);
3755 new[size-2] = '"';
3756 new[size-1] = '\0';
3757 }
3758 else
3759 {
3760 new[0] = '\0';
3761 }
3762 }
3763
3764 return new;
3765 }
3766 return NULL;
3767}
3768
3769
3770
3771void sh_hash_list_db_entry_full_detail (sh_file_t * p)
3772{
3773 char * tmp;
3774 char * esc;
3775 char str[81];
3776
3777 if (ListWithDelimiter == S_TRUE)
3778 {
3779 printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "),
3780 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3781 p->theFile.c_mode, (int) p->theFile.mode,
3782 p->theFile.c_attributes, (int) p->theFile.attributes,
3783 (int) p->theFile.hardlinks,
3784 p->theFile.c_owner, (int) p->theFile.owner,
3785 p->theFile.c_group, (int) p->theFile.group);
3786 }
3787 else
3788 {
3789 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
3790 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3791 p->theFile.c_mode, (int) p->theFile.mode,
3792 p->theFile.c_attributes, (int) p->theFile.attributes,
3793 (int) p->theFile.hardlinks,
3794 p->theFile.c_owner, (int) p->theFile.owner,
3795 p->theFile.c_group, (int) p->theFile.group);
3796 }
3797
3798 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3799 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev);
3800 else
3801 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size);
3802
3803 printf( _(" %8s"), str);
3804 if (ListWithDelimiter == S_TRUE)
3805 putchar(',');
3806
3807 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str)));
3808 if (ListWithDelimiter == S_TRUE)
3809 putchar(',');
3810 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str)));
3811 if (ListWithDelimiter == S_TRUE)
3812 putchar(',');
3813 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str)));
3814 if (ListWithDelimiter == S_TRUE)
3815 putchar(',');
3816 printf( _(" %s"), p->theFile.checksum);
3817 if (ListWithDelimiter == S_TRUE)
3818 putchar(',');
3819
3820 tmp = sh_util_safe_name(p->fullpath);
3821 if (ListWithDelimiter != S_TRUE)
3822 {
3823 printf( _(" %s"), tmp);
3824 }
3825 else
3826 {
3827 esc = csv_escape(tmp);
3828 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3829 if (esc)
3830 SH_FREE(esc);
3831 }
3832 SH_FREE(tmp);
3833
3834 if ('l' == p->theFile.c_mode[0])
3835 {
3836 tmp = sh_util_safe_name(p->linkpath);
3837 if (ListWithDelimiter != S_TRUE)
3838 {
3839 printf(_(" -> %s"), tmp);
3840 }
3841 else
3842 {
3843 esc = csv_escape(tmp);
3844 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3845 if (esc)
3846 SH_FREE(esc);
3847 }
3848 SH_FREE(tmp);
3849 }
3850
3851 if (p->attr_string)
3852 {
3853 tmp = sh_util_safe_name(p->attr_string);
3854 if (ListWithDelimiter != S_TRUE)
3855 {
3856 printf(_(" %s"), tmp);
3857 }
3858 else
3859 {
3860 esc = csv_escape(tmp);
3861 printf( _(" %s"), (esc != NULL) ? esc : _("(null)"));
3862 if (esc)
3863 SH_FREE(esc);
3864 }
3865 SH_FREE(tmp);
3866 }
3867 else
3868 {
3869 if (ListWithDelimiter == S_TRUE)
3870 printf(_(" no_attr"));
3871 }
3872 putchar('\n');
3873
3874 return;
3875}
3876
3877void sh_hash_list_db_entry (sh_file_t * p)
3878{
3879 char nowtime[128];
3880 char thetime[128];
3881 char * tmp;
3882 time_t now = time(NULL);
3883 time_t then = (time_t) p->theFile.mtime;
3884
3885#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
3886 struct tm * time_ptr;
3887 struct tm time_tm;
3888
3889 time_ptr = gmtime_r(&then, &time_tm);
3890 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
3891 time_ptr = gmtime_r(&now, &time_tm);
3892 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
3893 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3894 {
3895 time_ptr = gmtime_r(&then, &time_tm);
3896 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
3897 }
3898#else
3899 strftime(thetime, 127, _("%b %d %Y"), gmtime(&then));
3900 strftime(nowtime, 127, _("%b %d %Y"), gmtime(&now));
3901 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3902 strftime(thetime, 127, _("%b %d %H:%M"), gmtime(&then));
3903#endif
3904
3905 tmp = sh_util_safe_name(p->fullpath);
3906 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3907 printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"),
3908 p->theFile.c_mode, (int) p->theFile.hardlinks,
3909 p->theFile.c_owner, p->theFile.c_group,
3910 (int) major((dev_t)p->theFile.rdev),
3911 (int) minor((dev_t)p->theFile.rdev),
3912 thetime,
3913 tmp);
3914 else
3915 printf(_("%10s %3d %-8s %-8s %8ld %s %s"),
3916 p->theFile.c_mode, (int) p->theFile.hardlinks,
3917 p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size,
3918 thetime,
3919 tmp);
3920 SH_FREE(tmp);
3921
3922 if ('l' == p->theFile.c_mode[0])
3923 {
3924 tmp = sh_util_safe_name(p->linkpath);
3925 printf(_(" -> %s\n"), tmp);
3926 SH_FREE(tmp);
3927 }
3928 else
3929 printf("\n");
3930
3931 return;
3932}
3933
3934#ifdef HAVE_LIBZ
3935#include <zlib.h>
3936#endif
3937
3938int sh_hash_printcontent(char * linkpath)
3939{
3940#ifdef HAVE_LIBZ
3941 unsigned char * decoded;
3942 unsigned char * decompressed = NULL;
3943 size_t dlen;
3944 unsigned long clen;
3945 unsigned long clen_o;
3946 int res;
3947
3948 if (linkpath && *linkpath != '-')
3949 {
3950 dlen = sh_util_base64_dec_alloc (&decoded,
3951 (unsigned char *)linkpath,
3952 strlen(linkpath));
3953
3954 clen = dlen * 2 + 1;
3955
3956 do {
3957 if (decompressed)
3958 SH_FREE(decompressed);
3959 clen += dlen; clen_o = clen;
3960 decompressed = SH_ALLOC(clen);
3961 res = uncompress(decompressed, &clen, decoded, dlen);
3962 if (res == Z_MEM_ERROR)
3963 { fprintf(stderr, _("Error: Not enough memory\n")); return -1; }
3964 if (res == Z_DATA_ERROR)
3965 { fprintf(stderr, _("Error: Data corrupt or incomplete\n")); return -1; }
3966 } while (res == Z_BUF_ERROR || clen == clen_o);
3967
3968 decompressed[clen] = '\0';
3969 fputs( (char*) decompressed, stdout);
3970 return 0;
3971 }
3972#else
3973 (void) linkpath;
3974#endif
3975 fprintf(stderr, _("Error: No data available\n"));
3976 return -1;
3977}
3978
3979int sh_hash_list_db (const char * db_file)
3980{
3981 sh_file_t * p;
3982 SL_TICKET fd;
3983 char * line;
3984 int flag = 0;
3985
3986 if (!db_file)
3987 {
3988 _exit(EXIT_FAILURE);
3989 return -1;
3990 }
3991 if (sl_is_suid())
3992 {
3993 fprintf(stderr, _("ERROR: insufficient privilege\n"));
3994 _exit (EXIT_FAILURE);
3995 return -1; /* for Mac OSX compiler */
3996 }
3997 if (0 == strcmp(db_file, _("default")))
3998 db_file = file_path('D', 'W');
3999 if (!db_file)
4000 {
4001 _exit(EXIT_FAILURE);
4002 return -1;
4003 }
4004
4005 line = SH_ALLOC(MAX_PATH_STORE+2);
4006
4007 if ( SL_ISERROR(fd = sl_open_read(db_file, SL_YESPRIV)))
4008 {
4009 fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"),
4010 db_file, fd);
4011 _exit(EXIT_FAILURE);
4012 return -1;
4013 }
4014
4015 /* fast forward to start of data
4016 */
4017 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, db_file);
4018
4019 while (1)
4020 {
4021 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
4022 if ((p != NULL) && (p->fullpath[0] == '/'))
4023 {
4024 if (!ListFile)
4025 {
4026 flag = 1;
4027 if (ListFullDetail == S_FALSE)
4028 sh_hash_list_db_entry (p);
4029 else
4030 sh_hash_list_db_entry_full_detail (p);
4031 }
4032 else
4033 {
4034 if (0 != sl_strcmp(ListFile, p->fullpath))
4035 {
4036 continue;
4037 }
4038 flag = 1;
4039 if ('l' != p->theFile.c_mode[0])
4040 {
4041 if (sh_hash_printcontent(p->linkpath) < 0)
4042 {
4043 _exit(EXIT_FAILURE);
4044 return -1;
4045 }
4046 }
4047 else
4048 {
4049 fprintf(stderr, _("File is a link\n"));
4050 _exit(EXIT_FAILURE);
4051 return -1;
4052 }
4053 break;
4054 }
4055 }
4056 else if (p == NULL)
4057 {
4058 break;
4059 }
4060 }
4061
4062 if (line != NULL)
4063 SH_FREE(line);
4064 sl_close (fd);
4065
4066 fflush(NULL);
4067
4068 if (flag == 0)
4069 {
4070 fprintf(stderr, _("File not found\n"));
4071 _exit(EXIT_FAILURE);
4072 }
4073 _exit(EXIT_SUCCESS);
4074 return 0;
4075}
4076
4077/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
4078#endif
Note: See TracBrowser for help on using the repository browser.