source: trunk/src/sh_hash.c@ 170

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

Plenty of compiler warnings fixed, SQL query length fixed, doc update.

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