source: trunk/src/sh_hash.c@ 149

Last change on this file since 149 was 149, checked in by katerina, 17 years ago

Make sh_hash.c thread-safe, remove plenty of tiny allocations, improve sh_mem_dump, modify port check to run as thread, and fix unsetting of sh_thread_pause_flag (was too early).

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