source: trunk/src/sh_hash.c@ 159

Last change on this file since 159 was 153, checked in by katerina, 17 years ago

Use -D_FORTIFY_SOURCE=1 -fstack-protector-all if supported. Compiler warnings fixed.

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