source: trunk/src/sh_hash.c@ 163

Last change on this file since 163 was 162, checked in by katerina, 17 years ago

Fix for ticket #89, #90, and #91 (locking,compile failure).

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