source: trunk/src/sh_hash.c@ 193

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

Bugfixes for log monitoring, samba logfile parser.

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 int retval = 0;
1142 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.