source: trunk/src/sh_hash.c@ 140

Last change on this file since 140 was 137, checked in by rainer, 17 years ago

Fix compile errors.

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