source: trunk/src/sh_hash.c@ 85

Last change on this file since 85 was 77, checked in by rainer, 18 years ago

Fix for ticket #40 (No update if ReportOnlyOnce = False), and documentation
update.

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