source: trunk/src/sh_hash.c@ 135

Last change on this file since 135 was 133, checked in by rainer, 17 years ago

Reentrant checksum/hash functions.

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
2013 tmpFile.attr_string = NULL;
2014
2015 sl_strlcpy(tmpFile.fullpath, key, PATH_MAX);
2016 tmpFile.size = val1;
2017 tmpFile.mtime = val2;
2018 tmpFile.ctime = val3;
2019
2020 tmpFile.atime = 0;
2021 tmpFile.mode = 0;
2022 tmpFile.owner = 0;
2023 tmpFile.group = 0;
2024 sl_strlcpy(tmpFile.c_owner, _("root"), 5);
2025 sl_strlcpy(tmpFile.c_group, _("root"), 5);
2026
2027 if ((str != NULL) && (size < (PATH_MAX/2)-1))
2028 {
2029 tmpFile.c_mode[0] = 'l';
2030 tmpFile.c_mode[1] = 'r'; tmpFile.c_mode[2] = 'w';
2031 tmpFile.c_mode[3] = 'x'; tmpFile.c_mode[4] = 'r';
2032 tmpFile.c_mode[5] = 'w'; tmpFile.c_mode[6] = 'x';
2033 tmpFile.c_mode[7] = 'r'; tmpFile.c_mode[8] = 'w';
2034 tmpFile.c_mode[9] = 'x'; tmpFile.c_mode[10] = '\0';
2035 for (i = 0; i < size; ++i)
2036 {
2037 p = sh_util_charhex (str[i]);
2038 tmpFile.linkpath[2*i] = p[0];
2039 tmpFile.linkpath[2*i+1] = p[1];
2040 tmpFile.linkpath[2*i+2] = '\0';
2041 }
2042 }
2043 else
2044 {
2045 for (i = 0; i < 10; ++i)
2046 tmpFile.c_mode[i] = '-';
2047 tmpFile.c_mode[10] = '\0';
2048 tmpFile.linkpath[0] = '-';
2049 tmpFile.linkpath[1] = '\0';
2050 }
2051
2052 if (sh.flag.checkSum == SH_CHECK_CHECK &&
2053 sh.flag.update == S_TRUE)
2054 sh_hash_pushdata_memory (&tmpFile, SH_KEY_NULL);
2055 else
2056 sh_hash_pushdata (&tmpFile, SH_KEY_NULL);
2057
2058 return;
2059}
2060
2061extern int sh_util_hextobinary (char * binary, char * hex, int bytes);
2062
2063char * sh_hash_db2pop (char * key, unsigned long * val1,
2064 unsigned long * val2, unsigned long * val3,
2065 int * size)
2066{
2067 file_type tmpFile;
2068 size_t len;
2069 char * p;
2070 int i;
2071
2072 *size = 0;
2073
2074 if (0 == sh_hash_get_it (key, &tmpFile))
2075 {
2076 *val1 = tmpFile.size;
2077 *val2 = tmpFile.mtime;
2078 *val3 = tmpFile.ctime;
2079
2080 if (tmpFile.linkpath[0] != '-')
2081 {
2082 len = strlen(tmpFile.linkpath);
2083
2084 p = SH_ALLOC((len/2)+1);
2085 i = sh_util_hextobinary (p, tmpFile.linkpath, len);
2086
2087 if (i == 0)
2088 {
2089 *size = (len/2);
2090 p[*size] = '\0';
2091 return p;
2092 }
2093 else
2094 {
2095 SH_FREE(p);
2096 *size = 0;
2097 return NULL;
2098 }
2099 }
2100 else
2101 {
2102 *size = 0;
2103 return NULL;
2104 }
2105 }
2106 else
2107 {
2108 *size = -1;
2109 *val1 = 0;
2110 *val2 = 0;
2111 *val3 = 0;
2112 return NULL;
2113 }
2114}
2115
2116
2117
2118
2119/******************************************************************
2120 *
2121 * Data entry in hash table
2122 *
2123 ******************************************************************/
2124sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
2125{
2126 sh_file_t * fp;
2127 sh_filestore_t p;
2128
2129 size_t len;
2130 char * fullpath;
2131 char * linkpath;
2132 char * attr_string = NULL;
2133 char hashbuf[KEYBUF_SIZE];
2134
2135 SL_ENTER(_("sh_hash_push_int"));
2136
2137 fp = SH_ALLOC(sizeof(sh_file_t));
2138
2139 p.mark = REC_MAGIC;
2140 if (buf->attr_string)
2141 p.mark |= REC_FLAGS_ATTR;
2142 sl_strlcpy(p.c_mode, buf->c_mode, 11);
2143 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
2144 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
2145 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
2146#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2147 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
2148#endif
2149
2150#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2151 p.attributes = (UINT32) buf->attributes;
2152#endif
2153 p.linkmode = (UINT32) buf->linkmode;
2154 p.hardlinks = (UINT32) buf->hardlinks;
2155 p.dev = (UINT64) buf->dev;
2156 p.rdev = (UINT64) buf->rdev;
2157 p.mode = (UINT32) buf->mode;
2158 p.ino = (UINT32) buf->ino;
2159 p.size = (UINT64) buf->size;
2160 p.mtime = (UINT64) buf->mtime;
2161 p.atime = (UINT64) buf->atime;
2162 p.ctime = (UINT64) buf->ctime;
2163 p.owner = (UINT32) buf->owner;
2164 p.group = (UINT32) buf->group;
2165
2166 memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
2167 fp->fflags = 0; /* init fflags */
2168 fp->modi_mask = 0L;
2169
2170 if (buf->attr_string)
2171 attr_string = sh_util_strdup(buf->attr_string);
2172 fp->attr_string = attr_string;
2173
2174 len = sl_strlen(buf->fullpath);
2175 if (len <= MAX_PATH_STORE)
2176 {
2177 fullpath = SH_ALLOC(len+1);
2178 sl_strlcpy(fullpath, buf->fullpath, len+1);
2179 }
2180 else
2181 {
2182 fullpath = SH_ALLOC(KEY_LEN + 1);
2183 sl_strlcpy(fullpath,
2184 sh_tiger_hash (buf->fullpath, TIGER_DATA, len,
2185 hashbuf, sizeof(hashbuf)),
2186 KEY_LEN+1);
2187 }
2188 fp->fullpath = fullpath;
2189
2190 if (buf->c_mode[0] == 'l')
2191 {
2192 len = sl_strlen(buf->linkpath);
2193 if (len <= MAX_PATH_STORE)
2194 {
2195 linkpath = SH_ALLOC(len+1);
2196 sl_strlcpy(linkpath, buf->linkpath, len+1);
2197 }
2198 else
2199 {
2200 linkpath = SH_ALLOC(KEY_LEN + 1);
2201 sl_strlcpy(linkpath,
2202 sh_tiger_hash (buf->linkpath, TIGER_DATA, len,
2203 hashbuf, sizeof(hashbuf)),
2204 KEY_LEN+1);
2205 }
2206 fp->linkpath = linkpath;
2207 }
2208 else
2209 fp->linkpath = NULL;
2210
2211 SL_RETURN( fp, _("sh_hash_push_int"));
2212}
2213
2214#ifdef HAVE_INTTYPES_H
2215#include <inttypes.h>
2216#else
2217#ifdef HAVE_STDINT_H
2218#include <stdint.h>
2219#endif
2220#endif
2221
2222#ifndef PRIu64
2223#ifdef HAVE_LONG_32
2224#define PRIu64 "llu"
2225#else
2226#define PRIu64 "lu"
2227#endif
2228#endif
2229
2230char * sh_hash_size_format()
2231{
2232 static char form_rval[81];
2233
2234 SL_ENTER(_("sh_hash_size_format"));
2235
2236
2237#ifdef SH_USE_XML
2238 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2239 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
2240#else
2241 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2242 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
2243#endif
2244
2245 SL_RETURN( form_rval, _("sh_hash_size_format"));
2246}
2247
2248
2249#ifdef SH_USE_XML
2250static char * all_items (file_type * theFile, char * fileHash, int is_new)
2251{
2252 char timstr1c[32];
2253 char timstr1a[32];
2254 char timstr1m[32];
2255
2256 char * tmp_lnk;
2257 char * format;
2258
2259 char * tmp = SH_ALLOC(SH_BUFSIZE);
2260 char * msg = SH_ALLOC(SH_BUFSIZE);
2261
2262 tmp[0] = '\0';
2263 msg[0] = '\0';
2264
2265
2266#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2267 if (is_new)
2268 format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" ");
2269 else
2270 format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" ");
2271 sl_snprintf(tmp, SH_BUFSIZE, format,
2272 theFile->c_mode,
2273 theFile->c_attributes,
2274 (long) theFile->mode,
2275 (long) theFile->attributes
2276 );
2277#else
2278 if (is_new)
2279 format = _("mode_new=\"%s\" imode_new=\"%ld\" ");
2280 else
2281 format = _("mode_old=\"%s\" imode_old=\"%ld\" ");
2282
2283 sl_snprintf(tmp, SH_BUFSIZE, format,
2284 theFile->c_mode,
2285 (long) theFile->mode
2286 );
2287#endif
2288 sl_strlcat(msg, tmp, SH_BUFSIZE);
2289
2290 if (is_new)
2291 format = _("hardlinks_new=\"%lu\" ");
2292 else
2293 format = _("hardlinks_old=\"%lu\" ");
2294 sl_snprintf(tmp, SH_BUFSIZE, format,
2295 (unsigned long) theFile->hardlinks);
2296 sl_strlcat(msg, tmp, SH_BUFSIZE);
2297
2298
2299 if (is_new)
2300 format = _("idevice_new=\"%lu\" ");
2301 else
2302 format = _("idevice_old=\"%lu\" ");
2303 sl_snprintf(tmp, SH_BUFSIZE, format, (unsigned long) theFile->rdev);
2304 sl_strlcat(msg, tmp, SH_BUFSIZE);
2305
2306
2307 if (is_new)
2308 format = _("inode_new=\"%lu\" ");
2309 else
2310 format = _("inode_old=\"%lu\" ");
2311 sl_snprintf(tmp, SH_BUFSIZE, format, (unsigned long) theFile->ino);
2312 sl_strlcat(msg, tmp, SH_BUFSIZE);
2313
2314 /*
2315 * also report device for prelude
2316 */
2317#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
2318 if (is_new)
2319 format = _("dev_new=\"%lu,%lu\" ");
2320 else
2321 format = _("dev_old=\"%lu,%lu\" ");
2322 sl_snprintf(tmp, SH_BUFSIZE, format,
2323 (unsigned long) major(theFile->dev),
2324 (unsigned long) minor(theFile->dev));
2325 sl_strlcat(msg, tmp, SH_BUFSIZE);
2326#endif
2327
2328
2329 if (is_new)
2330 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
2331 else
2332 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
2333 sl_snprintf(tmp, SH_BUFSIZE, format,
2334 theFile->c_owner, (long) theFile->owner);
2335 sl_strlcat(msg, tmp, SH_BUFSIZE);
2336
2337
2338 if (is_new)
2339 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
2340 else
2341 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
2342 sl_snprintf(tmp, SH_BUFSIZE, format,
2343 theFile->c_group, (long) theFile->group);
2344 sl_strlcat(msg, tmp, SH_BUFSIZE);
2345
2346
2347 if (is_new)
2348 sl_snprintf(tmp, SH_BUFSIZE, sh_hash_size_format(),
2349 (UINT64) 0, (UINT64) theFile->size);
2350 else
2351 sl_snprintf(tmp, SH_BUFSIZE, sh_hash_size_format(),
2352 (UINT64) theFile->size, (UINT64) 0);
2353 sl_strlcat(msg, tmp, SH_BUFSIZE);
2354
2355
2356 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2357 if (is_new)
2358 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_new=\"%s\" "), timstr1c);
2359 else
2360 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_old=\"%s\" "), timstr1c);
2361 sl_strlcat(msg, tmp, SH_BUFSIZE);
2362
2363 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2364 if (is_new)
2365 sl_snprintf(tmp, SH_BUFSIZE, _("atime_new=\"%s\" "), timstr1a);
2366 else
2367 sl_snprintf(tmp, SH_BUFSIZE, _("atime_old=\"%s\" "), timstr1a);
2368 sl_strlcat(msg, tmp, SH_BUFSIZE);
2369
2370 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2371 if (is_new)
2372 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_new=\"%s\" "), timstr1m);
2373 else
2374 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_old=\"%s\" "), timstr1m);
2375 sl_strlcat(msg, tmp, SH_BUFSIZE);
2376
2377 if (is_new)
2378 sl_snprintf(tmp, SH_BUFSIZE, _("chksum_new=\"%s\" "), fileHash);
2379 else
2380 sl_snprintf(tmp, SH_BUFSIZE, _("chksum_old=\"%s\" "), fileHash);
2381 sl_strlcat(msg, tmp, SH_BUFSIZE);
2382
2383 if (theFile->c_mode[0] == 'l')
2384 {
2385 tmp_lnk = sh_util_safe_name(theFile->linkpath);
2386 if (tmp_lnk)
2387 {
2388 if (is_new)
2389 sl_snprintf(tmp, SH_BUFSIZE, _("link_new=\"%s\" "), tmp_lnk);
2390 else
2391 sl_snprintf(tmp, SH_BUFSIZE, _("link_old=\"%s\" "), tmp_lnk);
2392 SH_FREE(tmp_lnk);
2393 sl_strlcat(msg, tmp, SH_BUFSIZE);
2394 }
2395 }
2396
2397 if (theFile->attr_string)
2398 {
2399 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2400 if (tmp_lnk)
2401 {
2402 if (is_new)
2403 sl_snprintf(tmp, SH_BUFSIZE, _("acl_new=\"%s\" "), tmp_lnk);
2404 else
2405 sl_snprintf(tmp, SH_BUFSIZE, _("acl_old=\"%s\" "), tmp_lnk);
2406 SH_FREE(tmp_lnk);
2407 sl_strlcat(msg, tmp, SH_BUFSIZE);
2408 }
2409 }
2410
2411
2412 SH_FREE(tmp);
2413 return (msg);
2414}
2415#else
2416static char * all_items (file_type * theFile, char * fileHash, int is_new)
2417{
2418 char timstr1c[32];
2419 char timstr1a[32];
2420 char timstr1m[32];
2421
2422 char * tmp_lnk;
2423 char * format;
2424
2425 char * tmp = SH_ALLOC(SH_BUFSIZE);
2426 char * msg = SH_ALLOC(SH_BUFSIZE);
2427
2428 tmp[0] = '\0';
2429 msg[0] = '\0';
2430
2431
2432#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2433 if (is_new)
2434 format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, ");
2435 else
2436 format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, ");
2437 sl_snprintf(tmp, SH_BUFSIZE, format,
2438 theFile->c_mode,
2439 theFile->c_attributes,
2440 (long) theFile->mode,
2441 (long) theFile->attributes
2442 );
2443#else
2444 if (is_new)
2445 format = _("mode_new=<%s>, imode_new=<%ld>, ");
2446 else
2447 format = _("mode_old=<%s>, imode_old=<%ld>, ");
2448
2449 sl_snprintf(tmp, SH_BUFSIZE, format,
2450 theFile->c_mode,
2451 (long) theFile->mode
2452 );
2453#endif
2454 sl_strlcat(msg, tmp, SH_BUFSIZE);
2455
2456 if (is_new)
2457 format = _("hardlinks_new=<%lu>, ");
2458 else
2459 format = _("hardlinks_old=<%lu>, ");
2460 sl_snprintf(tmp, SH_BUFSIZE, format,
2461 (unsigned long) theFile->hardlinks);
2462 sl_strlcat(msg, tmp, SH_BUFSIZE);
2463
2464
2465 if (is_new)
2466 format = _("idevice_new=<%lu>, ");
2467 else
2468 format = _("idevice_old=<%lu>, ");
2469 sl_snprintf(tmp, SH_BUFSIZE, format, (unsigned long) theFile->rdev);
2470 sl_strlcat(msg, tmp, SH_BUFSIZE);
2471
2472
2473 if (is_new)
2474 format = _("inode_new=<%lu>, ");
2475 else
2476 format = _("inode_old=<%lu>, ");
2477 sl_snprintf(tmp, SH_BUFSIZE, format, (unsigned long) theFile->ino);
2478 sl_strlcat(msg, tmp, SH_BUFSIZE);
2479
2480
2481 /*
2482 * also report device for prelude
2483 */
2484#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
2485 if (is_new)
2486 format = _("dev_new=<%lu,%lu>, ");
2487 else
2488 format = _("dev_old=<%lu,%lu>, ");
2489 sl_snprintf(tmp, SH_BUFSIZE, format,
2490 (unsigned long) major(theFile->dev),
2491 (unsigned long) minor(theFile->dev));
2492 sl_strlcat(msg, tmp, SH_BUFSIZE);
2493#endif
2494
2495 if (is_new)
2496 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
2497 else
2498 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
2499 sl_snprintf(tmp, SH_BUFSIZE, format,
2500 theFile->c_owner, (long) theFile->owner);
2501 sl_strlcat(msg, tmp, SH_BUFSIZE);
2502
2503
2504 if (is_new)
2505 format = _("group_new=<%s>, igroup_new=<%ld>, ");
2506 else
2507 format = _("group_old=<%s>, igroup_old=<%ld>, ");
2508 sl_snprintf(tmp, SH_BUFSIZE, format,
2509 theFile->c_group, (long) theFile->group);
2510 sl_strlcat(msg, tmp, SH_BUFSIZE);
2511
2512
2513 if (is_new)
2514 sl_snprintf(tmp, SH_BUFSIZE, sh_hash_size_format(),
2515 (UINT64) 0, (UINT64) theFile->size);
2516 else
2517 sl_snprintf(tmp, SH_BUFSIZE, sh_hash_size_format(),
2518 (UINT64) theFile->size, (UINT64) 0);
2519 sl_strlcat(msg, tmp, SH_BUFSIZE);
2520
2521
2522 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2523 if (is_new)
2524 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_new=<%s>, "), timstr1c);
2525 else
2526 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_old=<%s>, "), timstr1c);
2527 sl_strlcat(msg, tmp, SH_BUFSIZE);
2528
2529 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2530 if (is_new)
2531 sl_snprintf(tmp, SH_BUFSIZE, _("atime_new=<%s>, "), timstr1a);
2532 else
2533 sl_snprintf(tmp, SH_BUFSIZE, _("atime_old=<%s>, "), timstr1a);
2534 sl_strlcat(msg, tmp, SH_BUFSIZE);
2535
2536 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2537 if (is_new)
2538 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_new=<%s>, "), timstr1m);
2539 else
2540 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_old=<%s>, "), timstr1m);
2541 sl_strlcat(msg, tmp, SH_BUFSIZE);
2542
2543 if (is_new)
2544 sl_snprintf(tmp, SH_BUFSIZE, _("chksum_new=<%s>"), fileHash);
2545 else
2546 sl_snprintf(tmp, SH_BUFSIZE, _("chksum_old=<%s>"), fileHash);
2547 sl_strlcat(msg, tmp, SH_BUFSIZE);
2548
2549 if (theFile->c_mode[0] == 'l')
2550 {
2551 tmp_lnk = sh_util_safe_name(theFile->linkpath);
2552 if (tmp_lnk)
2553 {
2554 if (is_new)
2555 sl_snprintf(tmp, SH_BUFSIZE, _(", link_new=<%s> "), tmp_lnk);
2556 else
2557 sl_snprintf(tmp, SH_BUFSIZE, _(", link_old=<%s> "), tmp_lnk);
2558 SH_FREE(tmp_lnk);
2559 sl_strlcat(msg, tmp, SH_BUFSIZE);
2560 }
2561 }
2562
2563 if (theFile->attr_string)
2564 {
2565 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2566 if (tmp_lnk)
2567 {
2568 if (is_new)
2569 sl_snprintf(tmp, SH_BUFSIZE, _(", acl_new=<%s> "), tmp_lnk);
2570 else
2571 sl_snprintf(tmp, SH_BUFSIZE, _(", acl_old=<%s> "), tmp_lnk);
2572 SH_FREE(tmp_lnk);
2573 sl_strlcat(msg, tmp, SH_BUFSIZE);
2574 }
2575 }
2576
2577 SH_FREE(tmp);
2578 return (msg);
2579}
2580#endif
2581
2582void sh_hash_pushdata_memory (file_type * theFile, char * fileHash)
2583{
2584 sh_file_t * p;
2585
2586 SL_ENTER(_("sh_hash_pushdata_memory"));
2587
2588 p = sh_hash_push_int(theFile, fileHash);
2589 if (p)
2590 {
2591 hashinsert (p);
2592 p->modi_mask = theFile->check_mask;
2593 }
2594
2595 SL_RET0(_("sh_hash_pushdata_memory"));
2596}
2597
2598
2599/*****************************************************************
2600 *
2601 * Compare a file with the database status.
2602 *
2603 *****************************************************************/
2604int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
2605 char * policy_override, int severity_override)
2606{
2607 char * msg;
2608 sh_file_t * p;
2609 char * tmp;
2610 char * tmp_path;
2611 char * tmp_lnk;
2612 char * tmp_lnk_old;
2613
2614 char * str;
2615
2616 char timstr1c[32];
2617 char timstr2c[32];
2618 char timstr1a[32];
2619 char timstr2a[32];
2620 char timstr1m[32];
2621 char timstr2m[32];
2622 char linkHash[KEY_LEN+1];
2623 int maxcomp;
2624
2625 char change_code[16];
2626 int i;
2627
2628 unsigned long modi_mask = 0;
2629
2630 char log_policy[32];
2631 int log_severity;
2632 char hashbuf[KEYBUF_SIZE];
2633
2634 SL_ENTER(_("sh_hash_compdata"));
2635
2636 if (IsInit != 1) sh_hash_init();
2637
2638 if (severity_override < 0)
2639 log_severity = ShDFLevel[class];
2640 else
2641 log_severity = severity_override;
2642
2643 if (policy_override != NULL)
2644 sl_strlcpy (log_policy, policy_override, 32);
2645
2646 /* -------- find the entry for the file ---------------- */
2647
2648 if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE)
2649 p = hashsearch(theFile->fullpath);
2650 else
2651 p = hashsearch( sh_tiger_hash(theFile->fullpath,
2652 TIGER_DATA,
2653 sl_strlen(theFile->fullpath),
2654 hashbuf, sizeof(hashbuf))
2655 );
2656
2657
2658 /* --------- Not found in database. ------------
2659 */
2660
2661 if (p == NULL)
2662 {
2663 if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
2664 {
2665 tmp = sh_util_safe_name(theFile->fullpath);
2666
2667 str = all_items (theFile, fileHash, 1);
2668 sh_error_handle (log_severity, FIL__, __LINE__, 0,
2669 MSG_FI_ADD2,
2670 tmp, str);
2671 SH_FREE(str);
2672
2673 SH_FREE(tmp);
2674 }
2675
2676 if (p)
2677 {
2678 SET_SH_FFLAG_VISITED(p->fflags);
2679 CLEAR_SH_FFLAG_CHECKED(p->fflags);
2680 }
2681
2682 if (sh.flag.reportonce == S_TRUE)
2683 SET_SH_FFLAG_REPORTED(theFile->file_reported);
2684
2685 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2686 {
2687 p = sh_hash_push_int(theFile, fileHash);
2688 hashinsert (p);
2689 if (p)
2690 p->modi_mask = theFile->check_mask;
2691 }
2692
2693 else if (S_TRUE == sh.flag.update)
2694 {
2695 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
2696 {
2697 p = sh_hash_push_int(theFile, fileHash);
2698 hashinsert (p);
2699 if (p)
2700 p->modi_mask = theFile->check_mask;
2701 }
2702 else
2703 {
2704 SL_RETURN(1, _("sh_hash_compdata"));
2705 }
2706 }
2707
2708 SL_RETURN(0, _("sh_hash_compdata"));
2709 }
2710 else
2711 {
2712 p->modi_mask = theFile->check_mask;
2713 }
2714
2715 /* initialize change_code */
2716 for (i = 0; i < 15; ++i)
2717 change_code[i] = '-';
2718 change_code[15] = '\0';
2719
2720 TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"),
2721 theFile->fullpath, fileHash, p->theFile.checksum));
2722
2723 if ( (fileHash != NULL) && (p->theFile.checksum != NULL) &&
2724 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
2725 (theFile->check_mask & MODI_CHK) != 0)
2726 {
2727 if ((theFile->check_mask & MODI_SGROW) == 0)
2728 {
2729 modi_mask |= MODI_CHK;
2730 change_code[0] = 'C';
2731 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
2732 }
2733 else
2734 {
2735 if (0 != strncmp (&fileHash[KEY_LEN + 1],
2736 p->theFile.checksum, KEY_LEN))
2737 {
2738 modi_mask |= MODI_CHK;
2739 change_code[0] = 'C';
2740 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
2741 }
2742 else
2743 {
2744 p->theFile.size = theFile->size;
2745 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2746 }
2747 }
2748 }
2749
2750 if (p->theFile.c_mode[0] == 'l')
2751 {
2752 if (sl_strlen(theFile->linkpath) >= MAX_PATH_STORE)
2753 {
2754 sl_strlcpy(linkHash,
2755 sh_tiger_hash(theFile->linkpath,
2756 TIGER_DATA,
2757 sl_strlen(theFile->linkpath),
2758 hashbuf, sizeof(hashbuf)),
2759 MAX_PATH_STORE+1);
2760 maxcomp = MAX_PATH_STORE;
2761 }
2762 else
2763 {
2764 sl_strlcpy(linkHash, theFile->linkpath, KEY_LEN + 1);
2765 maxcomp = KEY_LEN;
2766 }
2767
2768
2769 if ( sl_strncmp (linkHash, p->linkpath, maxcomp) != 0 &&
2770 (theFile->check_mask & MODI_LNK) != 0)
2771 {
2772 modi_mask |= MODI_LNK;
2773 change_code[1] = 'L';
2774 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2775 }
2776 }
2777
2778 if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b')
2779 {
2780 if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) ||
2781 minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
2782 (theFile->check_mask & MODI_RDEV) != 0)
2783 {
2784 modi_mask |= MODI_RDEV;
2785 change_code[2] = 'D';
2786 TPT ((0, FIL__, __LINE__, _("mod=<rdev>")));
2787 }
2788 }
2789
2790 /* cast to UINT32 in case ino_t is not 32bit
2791 */
2792 if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino &&
2793 (theFile->check_mask & MODI_INO) != 0)
2794 {
2795 modi_mask |= MODI_INO;
2796 change_code[3] = 'I';
2797 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2798 }
2799
2800 if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
2801 (theFile->check_mask & MODI_HLN) != 0)
2802 {
2803 modi_mask |= MODI_HLN;
2804 change_code[4] = 'H';
2805 TPT ((0, FIL__, __LINE__, _("mod=<hardlink>")));
2806 }
2807
2808
2809 if ( ( (theFile->mode != p->theFile.mode)
2810#if defined(USE_ACL) || defined(USE_XATTR)
2811 || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
2812 (
2813 (theFile->attr_string == NULL && p->attr_string != NULL) ||
2814 (theFile->attr_string != NULL && p->attr_string == NULL) ||
2815 (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
2816 )
2817 )
2818#endif
2819#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2820 || (theFile->attributes != p->theFile.attributes)
2821#endif
2822 )
2823 && (theFile->check_mask & MODI_MOD) != 0)
2824 {
2825 modi_mask |= MODI_MOD;
2826 change_code[5] = 'M';
2827 TPT ((0, FIL__, __LINE__, _("mod=<mode>")));
2828 /*
2829 * report link path if switch link/no link
2830 */
2831 if ((theFile->check_mask & MODI_LNK) != 0 &&
2832 (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
2833 (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
2834 {
2835 modi_mask |= MODI_LNK;
2836 change_code[1] = 'L';
2837 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2838 }
2839 }
2840
2841 if ( theFile->owner != (uid_t) p->theFile.owner &&
2842 (theFile->check_mask & MODI_USR) != 0)
2843 {
2844 modi_mask |= MODI_USR;
2845 change_code[6] = 'U';
2846 TPT ((0, FIL__, __LINE__, _("mod=<user>")));
2847 }
2848
2849 if ( theFile->group != (gid_t) p->theFile.group &&
2850 (theFile->check_mask & MODI_GRP) != 0)
2851 {
2852 modi_mask |= MODI_GRP;
2853 change_code[7] = 'G';
2854 TPT ((0, FIL__, __LINE__, _("mod=<group>")));
2855 }
2856
2857
2858 if ( theFile->mtime != (time_t) p->theFile.mtime &&
2859 (theFile->check_mask & MODI_MTM) != 0)
2860 {
2861 modi_mask |= MODI_MTM;
2862 change_code[8] = 'T';
2863 TPT ((0, FIL__, __LINE__, _("mod=<mtime>")));
2864 }
2865
2866 if ( (theFile->check_mask & MODI_ATM) != 0 &&
2867 theFile->atime != (time_t) p->theFile.atime)
2868 {
2869 modi_mask |= MODI_ATM;
2870 change_code[8] = 'T';
2871 TPT ((0, FIL__, __LINE__, _("mod=<atime>")));
2872 }
2873
2874
2875 /* Resetting the access time will set a new ctime. Thus, either we ignore
2876 * the access time or the ctime for NOIGNORE
2877 */
2878 if ( theFile->ctime != (time_t) p->theFile.ctime &&
2879 (theFile->check_mask & MODI_CTM) != 0)
2880 {
2881 modi_mask |= MODI_CTM;
2882 change_code[8] = 'T';
2883 TPT ((0, FIL__, __LINE__, _("mod=<ctime>")));
2884 }
2885
2886 if ( theFile->size != (off_t) p->theFile.size &&
2887 (theFile->check_mask & MODI_SIZ) != 0)
2888 {
2889 if ((theFile->check_mask & MODI_SGROW) == 0 ||
2890 theFile->size < (off_t) p->theFile.size)
2891 {
2892 modi_mask |= MODI_SIZ;
2893 change_code[9] = 'S';
2894 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
2895 }
2896 }
2897 change_code[10] = '\0';
2898
2899 /* --- Report full details. ---
2900 */
2901 if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
2902 {
2903 if ((theFile->check_mask & MODI_ATM) == 0)
2904 modi_mask = MASK_READONLY_;
2905 else
2906 modi_mask = MASK_NOIGNORE_;
2907 }
2908
2909 /* --- Report on modified files. ---
2910 */
2911 if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
2912 {
2913 tmp = SH_ALLOC(SH_BUFSIZE);
2914 msg = SH_ALLOC(SH_BUFSIZE);
2915 msg[0] = '\0';
2916
2917 if ( ((modi_mask & MODI_MOD) != 0)
2918#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
2919 || ((modi_mask & MODI_USR) != 0)
2920 || ((modi_mask & MODI_GRP) != 0)
2921#endif
2922 )
2923 {
2924#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2925 sl_snprintf(tmp, SH_BUFSIZE,
2926#ifdef SH_USE_XML
2927 _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "),
2928#else
2929 _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "),
2930#endif
2931 p->theFile.c_mode, theFile->c_mode,
2932 p->theFile.c_attributes, theFile->c_attributes
2933#ifdef SH_USE_XML
2934 , (long) p->theFile.mode, (long) theFile->mode,
2935 (long) p->theFile.attributes,
2936 (long) theFile->attributes
2937#endif
2938 );
2939#else
2940#ifdef SH_USE_XML
2941 sl_snprintf(tmp, SH_BUFSIZE,
2942 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
2943 p->theFile.c_mode, theFile->c_mode,
2944 (long) p->theFile.mode, (long) theFile->mode);
2945#else
2946 sl_snprintf(tmp, SH_BUFSIZE, _("mode_old=<%s>, mode_new=<%s>, "),
2947 p->theFile.c_mode, theFile->c_mode);
2948#endif
2949#endif
2950 sl_strlcat(msg, tmp, SH_BUFSIZE);
2951
2952#if defined(USE_ACL) || defined(USE_XATTR)
2953 if (theFile->attr_string != NULL || p->attr_string != NULL)
2954 {
2955 sl_snprintf(tmp, SH_BUFSIZE,
2956#ifdef SH_USE_XML
2957 _("acl_old=\"%s\" acl_new=\"%s\" "),
2958#else
2959 _("acl_old=<%s>, acl_new=<%s>, "),
2960#endif
2961 (p->attr_string) ? p->attr_string : _("none"),
2962 (theFile->attr_string) ? theFile->attr_string : _("none"));
2963
2964 sl_strlcat(msg, tmp, SH_BUFSIZE);
2965 }
2966#endif
2967
2968#ifdef REPLACE_OLD
2969 if ((modi_mask & MODI_MOD) != 0)
2970 {
2971 /*
2972 * We postpone update if sh.flag.update == S_TRUE because
2973 * in interactive mode the user may not accept the change.
2974 */
2975 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2976 {
2977 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
2978 p->theFile.mode = theFile->mode;
2979#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2980 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
2981 p->theFile.attributes = theFile->attributes;
2982#endif
2983#if defined(USE_ACL) || defined(USE_XATTR)
2984 if (p->attr_string == NULL && theFile->attr_string != NULL)
2985 { p->attr_string = sh_util_strdup (theFile->attr_string); }
2986 else if (p->attr_string != NULL && theFile->attr_string == NULL)
2987 { SH_FREE(p->attr_string); p->attr_string = NULL; }
2988 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2989 {
2990 if (0 != strcmp(theFile->attr_string, p->attr_string))
2991 {
2992 SH_FREE(p->attr_string);
2993 p->attr_string = sh_util_strdup (theFile->attr_string);
2994 }
2995 }
2996#endif
2997 }
2998 }
2999#endif
3000 }
3001
3002 if ((modi_mask & MODI_HLN) != 0)
3003 {
3004 sl_snprintf(tmp, SH_BUFSIZE,
3005#ifdef SH_USE_XML
3006 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
3007#else
3008 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
3009#endif
3010 (unsigned long) p->theFile.hardlinks,
3011 (unsigned long) theFile->hardlinks);
3012 sl_strlcat(msg, tmp, SH_BUFSIZE);
3013#ifdef REPLACE_OLD
3014 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3015 p->theFile.hardlinks = theFile->hardlinks;
3016#endif
3017 }
3018
3019 if ((modi_mask & MODI_RDEV) != 0)
3020 {
3021 sl_snprintf(tmp, SH_BUFSIZE,
3022#ifdef SH_USE_XML
3023 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
3024#else
3025 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
3026#endif
3027 (unsigned long) major(p->theFile.rdev),
3028 (unsigned long) minor(p->theFile.rdev),
3029 (unsigned long) major(theFile->rdev),
3030 (unsigned long) minor(theFile->rdev)
3031#ifdef SH_USE_XML
3032 , (unsigned long) p->theFile.rdev,
3033 (unsigned long) theFile->rdev
3034#endif
3035 );
3036 sl_strlcat(msg, tmp, SH_BUFSIZE);
3037#ifdef REPLACE_OLD
3038 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3039 p->theFile.rdev = theFile->rdev;
3040#endif
3041 }
3042
3043 if ((modi_mask & MODI_INO) != 0)
3044 {
3045 sl_snprintf(tmp, SH_BUFSIZE,
3046#ifdef SH_USE_XML
3047 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
3048#else
3049 _("inode_old=<%lu>, inode_new=<%lu>, "),
3050#endif
3051 (unsigned long) p->theFile.ino,
3052 (unsigned long) theFile->ino);
3053 sl_strlcat(msg, tmp, SH_BUFSIZE);
3054#ifdef REPLACE_OLD
3055 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3056 {
3057 p->theFile.ino = theFile->ino;
3058 p->theFile.dev = theFile->dev;
3059 }
3060#endif
3061 }
3062
3063
3064 /*
3065 * also report device for prelude
3066 */
3067#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
3068 if ((modi_mask & MODI_INO) != 0)
3069 {
3070 sl_snprintf(tmp, SH_BUFSIZE,
3071#ifdef SH_USE_XML
3072 _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "),
3073#else
3074 _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "),
3075#endif
3076 (unsigned long) major(p->theFile.dev),
3077 (unsigned long) minor(p->theFile.dev),
3078 (unsigned long) major(theFile->dev),
3079 (unsigned long) minor(theFile->dev)
3080 );
3081 sl_strlcat(msg, tmp, SH_BUFSIZE);
3082#ifdef REPLACE_OLD
3083 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3084 p->theFile.dev = theFile->dev;
3085#endif
3086 }
3087#endif
3088
3089 if ( ((modi_mask & MODI_USR) != 0)
3090#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
3091 || ((modi_mask & MODI_MOD) != 0)
3092#endif
3093 )
3094 {
3095#ifdef SH_USE_XML
3096 sl_snprintf(tmp, SH_BUFSIZE,
3097 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
3098#else
3099 sl_snprintf(tmp, SH_BUFSIZE,
3100 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
3101#endif
3102 p->theFile.c_owner, theFile->c_owner,
3103 (long) p->theFile.owner, (long) theFile->owner
3104 );
3105 sl_strlcat(msg, tmp, SH_BUFSIZE);
3106#ifdef REPLACE_OLD
3107 if ((modi_mask & MODI_USR) != 0) {
3108 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3109 {
3110 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3111 p->theFile.owner = theFile->owner;
3112 }
3113 }
3114#endif
3115 }
3116
3117 if ( ((modi_mask & MODI_GRP) != 0)
3118#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
3119 || ((modi_mask & MODI_MOD) != 0)
3120#endif
3121 )
3122 {
3123#ifdef SH_USE_XML
3124 sl_snprintf(tmp, SH_BUFSIZE,
3125 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
3126 p->theFile.c_group, theFile->c_group,
3127 (long) p->theFile.group, (long) theFile->group);
3128#else
3129 sl_snprintf(tmp, SH_BUFSIZE,
3130 _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "),
3131 p->theFile.c_group, theFile->c_group,
3132 (long) p->theFile.group, (long) theFile->group);
3133#endif
3134
3135 sl_strlcat(msg, tmp, SH_BUFSIZE);
3136#ifdef REPLACE_OLD
3137 if ((modi_mask & MODI_GRP) != 0) {
3138 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3139 {
3140 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3141 p->theFile.group = theFile->group;
3142 }
3143 }
3144#endif
3145 }
3146
3147 if ((modi_mask & MODI_SIZ) != 0)
3148 {
3149 sl_snprintf(tmp, SH_BUFSIZE, sh_hash_size_format(),
3150 (UINT64) p->theFile.size,
3151 (UINT64) theFile->size);
3152 sl_strlcat(msg, tmp, SH_BUFSIZE);
3153#ifdef REPLACE_OLD
3154 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3155 p->theFile.size = theFile->size;
3156#endif
3157 }
3158
3159 if ((modi_mask & MODI_CTM) != 0)
3160 {
3161 (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c));
3162 (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c));
3163#ifdef SH_USE_XML
3164 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
3165 timstr1c, timstr2c);
3166#else
3167 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_old=<%s>, ctime_new=<%s>, "),
3168 timstr1c, timstr2c);
3169#endif
3170 sl_strlcat(msg, tmp, SH_BUFSIZE);
3171#ifdef REPLACE_OLD
3172 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3173 p->theFile.ctime = theFile->ctime;
3174#endif
3175 }
3176
3177 if ((modi_mask & MODI_ATM) != 0)
3178 {
3179 (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a));
3180 (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a));
3181#ifdef SH_USE_XML
3182 sl_snprintf(tmp, SH_BUFSIZE, _("atime_old=\"%s\" atime_new=\"%s\" "),
3183 timstr1a, timstr2a);
3184#else
3185 sl_snprintf(tmp, SH_BUFSIZE, _("atime_old=<%s>, atime_new=<%s>, "),
3186 timstr1a, timstr2a);
3187#endif
3188 sl_strlcat(msg, tmp, SH_BUFSIZE);
3189#ifdef REPLACE_OLD
3190 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3191 p->theFile.atime = theFile->atime;
3192#endif
3193 }
3194
3195 if ((modi_mask & MODI_MTM) != 0)
3196 {
3197 (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m));
3198 (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m));
3199#ifdef SH_USE_XML
3200 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
3201 timstr1m, timstr2m);
3202#else
3203 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_old=<%s>, mtime_new=<%s>, "),
3204 timstr1m, timstr2m);
3205#endif
3206 sl_strlcat(msg, tmp, SH_BUFSIZE);
3207#ifdef REPLACE_OLD
3208 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3209 p->theFile.mtime = theFile->mtime;
3210#endif
3211 }
3212
3213
3214 if ((modi_mask & MODI_CHK) != 0)
3215 {
3216 sl_snprintf(tmp, SH_BUFSIZE,
3217#ifdef SH_USE_XML
3218 _("chksum_old=\"%s\" chksum_new=\"%s\" "),
3219#else
3220 _("chksum_old=<%s>, chksum_new=<%s>, "),
3221#endif
3222 p->theFile.checksum, fileHash);
3223 sl_strlcat(msg, tmp, SH_BUFSIZE);
3224#ifdef REPLACE_OLD
3225 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3226 {
3227 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3228 if ((theFile->check_mask & MODI_SGROW) != 0)
3229 p->theFile.size = theFile->size;
3230 }
3231#endif
3232 }
3233
3234
3235 if ((modi_mask & MODI_LNK) != 0 && theFile->c_mode[0] == 'l')
3236 {
3237 tmp_lnk = sh_util_safe_name(theFile->linkpath);
3238 tmp_lnk_old = sh_util_safe_name(p->linkpath);
3239#ifdef SH_USE_XML
3240 sl_snprintf(tmp, SH_BUFSIZE, _("link_old=\"%s\" link_new=\"%s\" "),
3241 tmp_lnk_old, tmp_lnk);
3242#else
3243 sl_snprintf(tmp, SH_BUFSIZE, _("link_old=<%s>, link_new=<%s>"),
3244 tmp_lnk_old, tmp_lnk);
3245#endif
3246 SH_FREE(tmp_lnk);
3247 SH_FREE(tmp_lnk_old);
3248 sl_strlcat(msg, tmp, SH_BUFSIZE);
3249#ifdef REPLACE_OLD
3250 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3251 {
3252 if (p->linkpath != NULL)
3253 SH_FREE(p->linkpath);
3254 p->linkpath = sh_util_strdup(theFile->linkpath);
3255 }
3256#endif
3257 }
3258
3259
3260 tmp_path = sh_util_safe_name(theFile->fullpath);
3261 sh_error_handle(log_severity, FIL__, __LINE__,
3262 (long) modi_mask, MSG_FI_CHAN,
3263 (policy_override == NULL) ? _(policy[class]):log_policy,
3264 change_code, tmp_path, msg);
3265
3266 SH_FREE(tmp_path);
3267 SH_FREE(tmp);
3268 SH_FREE(msg);
3269
3270#ifndef REPLACE_OLD
3271 SET_SH_FFLAG_REPORTED(p->fflags);
3272#endif
3273
3274 if (S_TRUE == sh.flag.update)
3275 {
3276 if (S_FALSE == sh_util_ask_update(theFile->fullpath))
3277 {
3278 /* user does not want to update, thus we replace
3279 * with data from the baseline database
3280 */
3281 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
3282 theFile->mode = p->theFile.mode;
3283#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3284 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
3285 theFile->attributes = p->theFile.attributes;
3286#endif
3287#if defined(USE_ACL) || defined(USE_XATTR)
3288 if (theFile->attr_string == NULL && p->attr_string != NULL)
3289 { theFile->attr_string = sh_util_strdup (p->attr_string); }
3290 else if (theFile->attr_string != NULL && p->attr_string == NULL)
3291 { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
3292 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3293 {
3294 if (0 != strcmp(theFile->attr_string, p->attr_string))
3295 {
3296 SH_FREE(theFile->attr_string);
3297 theFile->attr_string = sh_util_strdup (p->attr_string);
3298 }
3299 }
3300#endif
3301
3302 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
3303 {
3304 sl_strlcpy(theFile->linkpath, p->linkpath, PATH_MAX);
3305 }
3306 else
3307 {
3308 theFile->linkpath[0] = '-';
3309 theFile->linkpath[1] = '\0';
3310 }
3311
3312 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
3313
3314 theFile->mtime = p->theFile.mtime;
3315 theFile->ctime = p->theFile.ctime;
3316 theFile->atime = p->theFile.atime;
3317
3318 theFile->size = p->theFile.size;
3319
3320 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
3321 theFile->group = p->theFile.group;
3322 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
3323 theFile->owner = p->theFile.owner;
3324
3325 theFile->ino = p->theFile.ino;
3326 theFile->rdev = p->theFile.rdev;
3327 theFile->dev = p->theFile.dev;
3328 theFile->hardlinks = p->theFile.hardlinks;
3329
3330 SET_SH_FFLAG_VISITED(p->fflags);
3331 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3332 SL_RETURN(1, _("sh_hash_compdata"));
3333 }
3334 else /* if (sh.flag.reportonce == S_TRUE) */
3335 {
3336 /* we replace the data in the in-memory copy of the
3337 * baseline database, because otherwise we would get
3338 * another warning if the suidcheck runs
3339 */
3340 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3341 p->theFile.mode = theFile->mode;
3342#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3343 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
3344 p->theFile.attributes = theFile->attributes;
3345#endif
3346#if defined(USE_ACL) || defined(USE_XATTR)
3347 if (p->attr_string == NULL && theFile->attr_string != NULL)
3348 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3349 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3350 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3351 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3352 {
3353 if (0 != strcmp(theFile->attr_string, p->attr_string))
3354 {
3355 SH_FREE(p->attr_string);
3356 p->attr_string = sh_util_strdup (theFile->attr_string);
3357 }
3358 }
3359#endif
3360
3361 if (theFile->c_mode[0] == 'l')
3362 {
3363 if (p->linkpath != NULL)
3364 SH_FREE(p->linkpath);
3365 p->linkpath = sh_util_strdup(theFile->linkpath);
3366 }
3367 else
3368 {
3369 if (p->linkpath != NULL) {
3370 p->linkpath[0] = '-';
3371 p->linkpath[1] = '\0';
3372 } else {
3373 p->linkpath = SH_ALLOC(2);
3374 p->linkpath[0] = '-';
3375 p->linkpath[1] = '\0';
3376 }
3377 }
3378
3379 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3380
3381 p->theFile.mtime = theFile->mtime;
3382 p->theFile.ctime = theFile->ctime;
3383 p->theFile.atime = theFile->atime;
3384
3385 p->theFile.size = theFile->size;
3386
3387 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3388 p->theFile.group = theFile->group;
3389 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3390 p->theFile.owner = theFile->owner;
3391
3392 p->theFile.ino = theFile->ino;
3393 p->theFile.rdev = theFile->rdev;
3394 p->theFile.dev = theFile->dev;
3395 p->theFile.hardlinks = theFile->hardlinks;
3396 }
3397 }
3398 }
3399
3400 SET_SH_FFLAG_VISITED(p->fflags);
3401 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3402
3403 SL_RETURN(0, _("sh_hash_compdata"));
3404}
3405
3406int hash_full_tree ()
3407{
3408 sh_file_t * p;
3409 int i;
3410
3411 SL_ENTER(_("sh_hash_compdata"));
3412
3413 if (IsInit != 1)
3414 SL_RETURN(0, _("sh_hash_compdata"));
3415
3416 for (i = 0; i < TABSIZE; ++i)
3417 {
3418 for (p = tab[i]; p; p = p->next)
3419 CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
3420 }
3421 SL_RETURN (0, _("sh_hash_compdata"));
3422}
3423
3424
3425int hash_remove_tree (char * s)
3426{
3427 sh_file_t * p;
3428 size_t len;
3429 unsigned int i;
3430
3431 SL_ENTER(_("hash_remove_tree"));
3432
3433 if (!s || *s == '\0')
3434 SL_RETURN ((-1), _("hash_remove_tree"));
3435
3436 len = sl_strlen(s);
3437
3438 if (IsInit != 1)
3439 sh_hash_init();
3440
3441 for (i = 0; i < TABSIZE; ++i)
3442 {
3443 for (p = tab[i]; p; p = p->next)
3444 {
3445 if (p->fullpath && 0 == strncmp(s, p->fullpath, len))
3446 {
3447 SET_SH_FFLAG_ALLIGNORE(p->fflags);
3448 }
3449 }
3450 }
3451 SL_RETURN ((0), _("hash_remove_tree"));
3452}
3453
3454#if TIME_WITH_SYS_TIME
3455#include <sys/time.h>
3456#include <time.h>
3457#else
3458#if HAVE_SYS_TIME_H
3459#include <sys/time.h>
3460#else
3461#include <time.h>
3462#endif
3463#endif
3464
3465static int ListFullDetail = S_FALSE;
3466static int ListWithDelimiter = S_FALSE;
3467
3468int set_full_detail (const char * c)
3469{
3470 ListFullDetail = S_TRUE;
3471 /* warning: unused parameter `c' */
3472 if (c)
3473 return 0;
3474 else
3475 return 0;
3476}
3477
3478int set_list_delimited (const char * c)
3479{
3480 ListFullDetail = S_TRUE;
3481 ListWithDelimiter = S_TRUE;
3482 /* warning: unused parameter `c' */
3483 if (c)
3484 return 0;
3485 else
3486 return 0;
3487}
3488
3489/* Always quote the string, except if it is empty. Qoute quotes by
3490 * doubling them.
3491 */
3492char * csv_escape(const char * str)
3493{
3494 const char * p = str;
3495 const char * q;
3496
3497 size_t size = 0;
3498 size_t flag_quote = 0;
3499 int flag_comma = 0;
3500 char * new;
3501 char * pnew;
3502
3503 if (p)
3504 {
3505
3506 while (*p)
3507 {
3508 if (*p == ',')
3509 flag_comma = 1;
3510 else if (*p == '"')
3511 ++flag_quote;
3512
3513 ++size; ++p;
3514 }
3515
3516 if (sl_ok_adds(size, flag_quote))
3517 size += flag_quote; /* double each quote */
3518 else
3519 return NULL;
3520
3521 if (sl_ok_adds(size, 3))
3522 size += 3; /* two quotes and terminating null */
3523 else
3524 return NULL;
3525
3526 new = SH_ALLOC(size);
3527
3528 if (flag_quote != 0)
3529 {
3530 new[0] = '"';
3531 pnew = &new[1];
3532 q = str;
3533 while (*q)
3534 {
3535 *pnew = *q;
3536 if (*pnew == '"')
3537 {
3538 ++pnew; *pnew = '"';
3539 }
3540 ++pnew; ++q;
3541 }
3542 *pnew = '"'; ++pnew;
3543 *pnew = '\0';
3544 }
3545 else
3546 {
3547 if (size > 3)
3548 {
3549 new[0] = '"';
3550 sl_strlcpy (&new[1], str, size-1);
3551 new[size-2] = '"';
3552 new[size-1] = '\0';
3553 }
3554 else
3555 {
3556 new[0] = '\0';
3557 }
3558 }
3559
3560 return new;
3561 }
3562 return NULL;
3563}
3564
3565
3566
3567void sh_hash_list_db_entry_full_detail (sh_file_t * p)
3568{
3569 char * tmp;
3570 char * esc;
3571 char str[81];
3572
3573 if (ListWithDelimiter == S_TRUE)
3574 {
3575 printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "),
3576 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3577 p->theFile.c_mode, (int) p->theFile.mode,
3578 p->theFile.c_attributes, (int) p->theFile.attributes,
3579 (int) p->theFile.hardlinks,
3580 p->theFile.c_owner, (int) p->theFile.owner,
3581 p->theFile.c_group, (int) p->theFile.group);
3582 }
3583 else
3584 {
3585 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
3586 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3587 p->theFile.c_mode, (int) p->theFile.mode,
3588 p->theFile.c_attributes, (int) p->theFile.attributes,
3589 (int) p->theFile.hardlinks,
3590 p->theFile.c_owner, (int) p->theFile.owner,
3591 p->theFile.c_group, (int) p->theFile.group);
3592 }
3593
3594 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3595 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev);
3596 else
3597 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size);
3598
3599 printf( _(" %8s"), str);
3600 if (ListWithDelimiter == S_TRUE)
3601 putchar(',');
3602
3603 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str)));
3604 if (ListWithDelimiter == S_TRUE)
3605 putchar(',');
3606 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str)));
3607 if (ListWithDelimiter == S_TRUE)
3608 putchar(',');
3609 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str)));
3610 if (ListWithDelimiter == S_TRUE)
3611 putchar(',');
3612 printf( _(" %s"), p->theFile.checksum);
3613 if (ListWithDelimiter == S_TRUE)
3614 putchar(',');
3615
3616 tmp = sh_util_safe_name(p->fullpath);
3617 if (ListWithDelimiter != S_TRUE)
3618 {
3619 printf( _(" %s"), tmp);
3620 }
3621 else
3622 {
3623 esc = csv_escape(tmp);
3624 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3625 if (esc)
3626 SH_FREE(esc);
3627 }
3628 SH_FREE(tmp);
3629
3630 if ('l' == p->theFile.c_mode[0])
3631 {
3632 tmp = sh_util_safe_name(p->linkpath);
3633 if (ListWithDelimiter != S_TRUE)
3634 {
3635 printf(_(" -> %s"), tmp);
3636 }
3637 else
3638 {
3639 esc = csv_escape(tmp);
3640 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3641 if (esc)
3642 SH_FREE(esc);
3643 }
3644 SH_FREE(tmp);
3645 }
3646
3647 if (p->attr_string)
3648 {
3649 tmp = sh_util_safe_name(p->attr_string);
3650 if (ListWithDelimiter != S_TRUE)
3651 {
3652 printf(_(" %s"), tmp);
3653 }
3654 else
3655 {
3656 esc = csv_escape(tmp);
3657 printf( _(" %s"), (esc != NULL) ? esc : _("(null)"));
3658 if (esc)
3659 SH_FREE(esc);
3660 }
3661 SH_FREE(tmp);
3662 }
3663 else
3664 {
3665 if (ListWithDelimiter == S_TRUE)
3666 printf(_(" no_attr"));
3667 }
3668 putchar('\n');
3669
3670 return;
3671}
3672
3673void sh_hash_list_db_entry (sh_file_t * p)
3674{
3675 char nowtime[128];
3676 char thetime[128];
3677 char * tmp;
3678 time_t now = time(NULL);
3679 time_t then = (time_t) p->theFile.mtime;
3680
3681#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
3682 struct tm * time_ptr;
3683 struct tm time_tm;
3684
3685 time_ptr = gmtime_r(&then, &time_tm);
3686 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
3687 time_ptr = gmtime_r(&now, &time_tm);
3688 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
3689 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3690 {
3691 time_ptr = gmtime_r(&then, &time_tm);
3692 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
3693 }
3694#else
3695 strftime(thetime, 127, _("%b %d %Y"), gmtime(&then));
3696 strftime(nowtime, 127, _("%b %d %Y"), gmtime(&now));
3697 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3698 strftime(thetime, 127, _("%b %d %H:%M"), gmtime(&then));
3699#endif
3700
3701 tmp = sh_util_safe_name(p->fullpath);
3702 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3703 printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"),
3704 p->theFile.c_mode, (int) p->theFile.hardlinks,
3705 p->theFile.c_owner, p->theFile.c_group,
3706 (int) major((dev_t)p->theFile.rdev),
3707 (int) minor((dev_t)p->theFile.rdev),
3708 thetime,
3709 tmp);
3710 else
3711 printf(_("%10s %3d %-8s %-8s %8ld %s %s"),
3712 p->theFile.c_mode, (int) p->theFile.hardlinks,
3713 p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size,
3714 thetime,
3715 tmp);
3716 SH_FREE(tmp);
3717
3718 if ('l' == p->theFile.c_mode[0])
3719 {
3720 tmp = sh_util_safe_name(p->linkpath);
3721 printf(_(" -> %s\n"), tmp);
3722 SH_FREE(tmp);
3723 }
3724 else
3725 printf("\n");
3726
3727 return;
3728}
3729
3730int sh_hash_list_db (const char * db_file)
3731{
3732 sh_file_t * p;
3733 SL_TICKET fd;
3734 char * line;
3735
3736 if (!db_file)
3737 {
3738 _exit(EXIT_FAILURE);
3739 return -1;
3740 }
3741 if (sl_is_suid())
3742 {
3743 fprintf(stderr, _("ERROR: insufficient privilege\n"));
3744 _exit (EXIT_FAILURE);
3745 return -1; /* for Mac OSX compiler */
3746 }
3747 if (0 == strcmp(db_file, _("default")))
3748 db_file = file_path('D', 'W');
3749 if (!db_file)
3750 {
3751 _exit(EXIT_FAILURE);
3752 return -1;
3753 }
3754
3755 line = SH_ALLOC(MAX_PATH_STORE+1);
3756
3757 if ( SL_ISERROR(fd = sl_open_read(db_file, SL_YESPRIV)))
3758 {
3759 fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"),
3760 db_file, fd);
3761 _exit(EXIT_FAILURE);
3762 return -1;
3763 }
3764
3765 /* fast forward to start of data
3766 */
3767 sh_hash_setdataent(fd, line, MAX_PATH_STORE, db_file);
3768
3769 while (1)
3770 {
3771 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE);
3772 if ((p != NULL) && (p->fullpath[0] != 'K'))
3773 {
3774 if (ListFullDetail == S_FALSE)
3775 sh_hash_list_db_entry (p);
3776 else
3777 sh_hash_list_db_entry_full_detail (p);
3778 }
3779 else if (p == NULL)
3780 {
3781 break;
3782 }
3783 }
3784
3785 if (line != NULL)
3786 SH_FREE(line);
3787 sl_close (fd);
3788
3789 fflush(NULL);
3790
3791 _exit(EXIT_SUCCESS);
3792 return 0;
3793}
3794
3795/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
3796#endif
Note: See TracBrowser for help on using the repository browser.