source: trunk/src/sh_hash.c@ 121

Last change on this file since 121 was 115, checked in by rainer, 17 years ago

Fix the problem that new suid/sgid file found by the file system check already will not be quarantined in the suid check (ticket #71).

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