source: trunk/src/sh_hash.c@ 201

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

While we're at it, implement 'else' cor the config file conditionals. Also fix some compile warnings and improve docs.

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