source: trunk/src/sh_hash.c@ 169

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

Fixes for tickes #93 to #104 (yes, big commit, bad, bad,...).

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