source: trunk/src/sh_hash.c@ 104

Last change on this file since 104 was 93, checked in by rainer, 18 years ago

Add check for PCI ROMs; fix ticket #51 (symlinks in root directory reported with leading double slash).

File size: 89.6 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000, 2001, 2002 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22/* define this if you want version 1.3 style database file */
23/* #define OLD_BUG */
24
25/* make sure state changes of a file are always reported, even
26 * with reportonlyonce=true
27 */
28/* #define REPLACE_OLD *//* moved to samhain.h */
29
30#include <stdlib.h>
31#include <string.h>
32#include <stdio.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <unistd.h>
36
37#ifdef MAJOR_IN_MKDEV
38#include <sys/mkdev.h>
39#else
40#ifdef MAJOR_IN_SYSMACROS
41#include <sys/sysmacros.h>
42#endif
43#endif
44
45#ifdef HAVE_MEMORY_H
46#include <memory.h>
47#endif
48
49#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
50
51#include "sh_hash.h"
52#include "sh_utils.h"
53#include "sh_error.h"
54#include "sh_tiger.h"
55#include "sh_gpg.h"
56#include "sh_unix.h"
57#include "sh_files.h"
58#include "sh_ignore.h"
59
60#if defined(SH_WITH_CLIENT)
61#include "sh_forward.h"
62#endif
63
64#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
71char * unquote_string (const char * str)
72{
73 int i = 0, t1, t2;
74 char * tmp = NULL;
75 size_t len, l2, j, k = 0;
76
77 SL_ENTER(_("unquote_string"));
78
79 if (str != NULL)
80 {
81 len = sl_strlen(str);
82 l2 = len - 2;
83 tmp = SH_ALLOC(len + 1);
84
85 for (j = 0; j <= len; ++j)
86 {
87 if (str[j] != QUOTE_CHAR)
88 {
89 tmp[k] = str[j];
90 }
91 else if (str[j] == QUOTE_CHAR && j < l2)
92 {
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 }
105 }
106 else
107 tmp[k] = str[j];
108 ++k;
109 }
110 }
111 SL_RETURN(tmp, _("unquote_string"));
112}
113
114static char i2h[2];
115
116char * int2hex (unsigned char i)
117{
118 static char hexchars[] = "0123456789ABCDEF";
119
120 i2h[0] = hexchars[(((i) & 0xF0) >> 4)]; /* high */
121 i2h[1] = hexchars[((i) & 0x0F)]; /* low */
122
123 return i2h;
124}
125
126
127char * quote_string (const char * str)
128{
129 char * tmp;
130 char * tmp2;
131 size_t len, l2, j, i = 0, k = 0;
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
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
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;
287 char * attr_string;
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]"),
305 N_("[User2]"),
306 N_("[User3]"),
307 N_("[User4]"),
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 */
323/* #define TABSIZE 2048 */
324#define TABSIZE 65536
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
340#define REC_FLAGS_ATTR (1<<8)
341#define REC_FLAGS_MASK 0xFF00
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;
351#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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;
361#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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
394 if (p->attr_string)
395 theFile->attr_string = sh_util_strdup(p->attr_string);
396 else
397 theFile->attr_string = NULL;
398
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 **************************************************************/
411
412static int hashfunc(char *s)
413{
414 unsigned int n = 0;
415
416 for ( ; *s; s++)
417 n = 31 * n + *s;
418
419 return n & (TABSIZE - 1); /* % TABSIZE */;
420}
421
422
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);
450 if (theFile->attr_string)
451 SH_FREE(theFile->attr_string);
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 {
509 ptr = sh_util_dirname (p->fullpath);
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);
529 if (theFile->attr_string)
530 SH_FREE(theFile->attr_string);
531 SH_FREE(theFile);
532
533 SH_FREE(tmp);
534 }
535 }
536
537 /* We rewrite the db on update, thus we need to keep this
538 * if the user does not want to purge it from the db.
539 */
540
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)))
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 }
561 if (p->attr_string)
562 {
563 SH_FREE(p->attr_string);
564 p->attr_string = NULL;
565 }
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);
588 if (theFile->attr_string)
589 SH_FREE(theFile->attr_string);
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 }
650 if (p->attr_string)
651 {
652 SH_FREE(p->attr_string);
653 p->attr_string = NULL;
654 }
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
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 }
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;
690 sh_file_t * q;
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 &&
709 0 == strcmp(s->fullpath, p->fullpath))
710 {
711 q = p->next;
712 SH_FREE(p->fullpath);
713 if(p->linkpath)
714 SH_FREE(p->linkpath);
715 if(p->attr_string)
716 SH_FREE(p->attr_string);
717 memcpy(p, s, sizeof(sh_file_t));
718 p->next = q;
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) {
750 if (sizeofline > 0) line[0] = '\0';
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;
762 line[n] = '\0'; /* remove terminating '\n' */
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 ******************************************************************/
788int sh_hash_setdataent (SL_TICKET fd, char * line, int size, const char * file)
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 {
817 i = sh_hash_getline (sh_fin_fd, line, size);
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;
886 size_t len;
887 char * fullpath;
888 char * linkpath;
889 char * attr_string = NULL;
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));
921#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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
930 if ((ft.mark & ~REC_FLAGS_MASK) != REC_MAGIC)
931 {
932 SH_FREE(p);
933 SL_RETURN( NULL, _("sh_hash_getdataent"));
934 }
935
936 /* Read next record -- Part Two -- Fullpath
937 */
938 i = sh_hash_getline (sh_fin_fd, line, size);
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);
954 len = sl_strlen(tmp)+1;
955 fullpath = SH_ALLOC(len);
956 (void) sl_strlcpy (fullpath, tmp, len);
957 if (tmp)
958 SH_FREE(tmp);
959 if (fullpath[len-2] == '\n')
960 fullpath[len-2] = '\0';
961
962 /* Read next record -- Part Three -- Linkpath
963 */
964 i = sh_hash_getline (sh_fin_fd, line, size);
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);
981 len = sl_strlen(tmp)+1;
982 linkpath = SH_ALLOC(len);
983 (void) sl_strlcpy (linkpath, tmp, len);
984 if (tmp)
985 SH_FREE(tmp);
986 if (linkpath[len-2] == '\n')
987 linkpath[len-2] = '\0';
988
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
1021 /* Read next record -- Part Four -- Decode
1022 */
1023#if defined(SH_STEALTH)
1024 sh_do_decode(fullpath, sl_strlen(fullpath));
1025
1026#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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 }
1040 if ((ft.mark & REC_FLAGS_ATTR) != 0)
1041 {
1042 sh_do_decode(attr_string, sl_strlen(attr_string));
1043 }
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
1054 p->attr_string = attr_string;
1055
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{
1070
1071#define FGETS_BUF 16384
1072
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");
1180 buf = SH_ALLOC(FGETS_BUF);
1181
1182 while (NULL != fgets(buf, FGETS_BUF, fin_cp))
1183 {
1184 bufc = 0;
1185 while (bufc < FGETS_BUF) {
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
1331int sh_hash_pushdata_stdout (const char * str)
1332{
1333 if (!str)
1334 { pushdata_stdout = S_TRUE; return 0; }
1335 return -1;
1336}
1337
1338int sh_hash_version_string(const char * str)
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 }
1350 sh_db_version_string = sh_util_strdup(str);
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;
1373 char * attr_string = NULL;
1374
1375 char * line = NULL;
1376
1377 char timestring[81];
1378 char * timep;
1379
1380#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
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 {
1453 if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
1454 {
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 }
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
1512 if (tmp && tmp_len <= MAX_PATH_STORE)
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 }
1530 if (tmp) SH_FREE(tmp);
1531 }
1532
1533#if defined(SH_STEALTH)
1534 sh_do_encode(fullpath, sl_strlen(fullpath));
1535#endif
1536
1537 tmp = quote_string(fullpath);
1538 if (tmp) {
1539 sl_strlcpy(fullpath, tmp, MAX_PATH_STORE+1);
1540 SH_FREE(tmp);
1541 }
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
1556 if (tmp && tmp_len <= MAX_PATH_STORE)
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 }
1567 if (tmp) SH_FREE(tmp);
1568
1569#if defined(SH_STEALTH)
1570 sh_do_encode(linkpath, sl_strlen(linkpath));
1571#endif
1572 tmp = quote_string(linkpath);
1573 if (tmp)
1574 {
1575 sl_strlcpy(linkpath, tmp, MAX_PATH_STORE+1);
1576 SH_FREE(tmp);
1577 }
1578 }
1579
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
1598 if (buf != NULL) {
1599 p.mark = REC_MAGIC;
1600 if (attr_string)
1601 p.mark |= REC_FLAGS_ATTR;
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 }
1608#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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
1624#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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));
1720 sl_write_line_fast (pushdata_fd, fullpath, sl_strlen(fullpath));
1721 sl_write_line_fast (pushdata_fd, linkpath, sl_strlen(linkpath));
1722 if (attr_string)
1723 sl_write_line_fast (pushdata_fd, attr_string, sl_strlen(attr_string));
1724 } else {
1725 fwrite (&p, sizeof(sh_filestore_t), 1, stdout);
1726 printf ("%s\n", fullpath);
1727 printf ("%s\n", linkpath);
1728 if (attr_string)
1729 printf ("%s\n", attr_string);
1730 }
1731
1732 ++p_count;
1733
1734 if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
1735 {
1736 if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
1737 {
1738 sl_close (pushdata_fd);
1739 pushdata_fd = -1;
1740 }
1741 }
1742
1743 SH_FREE(fullpath);
1744 SH_FREE(linkpath);
1745 if (attr_string)
1746 SH_FREE(attr_string);
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);
1780 if (f->attr_string)
1781 SH_FREE(f->attr_string);
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;
1850
1851 tmpFile->attr_string = NULL;
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
1928void sh_hash_push2db (char * key, unsigned long val1,
1929 unsigned long val2, unsigned long val3,
1930 unsigned char * str, int size)
1931{
1932 file_type tmpFile;
1933 int i = 0;
1934 char * p;
1935
1936 tmpFile.attr_string = NULL;
1937
1938 sl_strlcpy(tmpFile.fullpath, key, PATH_MAX);
1939 tmpFile.size = val1;
1940 tmpFile.mtime = val2;
1941 tmpFile.ctime = val3;
1942
1943 tmpFile.atime = 0;
1944 tmpFile.mode = 0;
1945 tmpFile.owner = 0;
1946 tmpFile.group = 0;
1947 sl_strlcpy(tmpFile.c_owner, _("root"), 5);
1948 sl_strlcpy(tmpFile.c_group, _("root"), 5);
1949
1950 if ((str != NULL) && (size < (PATH_MAX/2)-1))
1951 {
1952 tmpFile.c_mode[0] = 'l';
1953 tmpFile.c_mode[1] = 'r'; tmpFile.c_mode[2] = 'w';
1954 tmpFile.c_mode[3] = 'x'; tmpFile.c_mode[4] = 'r';
1955 tmpFile.c_mode[5] = 'w'; tmpFile.c_mode[6] = 'x';
1956 tmpFile.c_mode[7] = 'r'; tmpFile.c_mode[8] = 'w';
1957 tmpFile.c_mode[9] = 'x'; tmpFile.c_mode[10] = '\0';
1958 for (i = 0; i < size; ++i)
1959 {
1960 p = sh_util_charhex (str[i]);
1961 tmpFile.linkpath[2*i] = p[0];
1962 tmpFile.linkpath[2*i+1] = p[1];
1963 tmpFile.linkpath[2*i+2] = '\0';
1964 }
1965 }
1966 else
1967 {
1968 for (i = 0; i < 10; ++i)
1969 tmpFile.c_mode[i] = '-';
1970 tmpFile.c_mode[10] = '\0';
1971 tmpFile.linkpath[0] = '-';
1972 tmpFile.linkpath[1] = '\0';
1973 }
1974
1975 if (sh.flag.checkSum == SH_CHECK_CHECK &&
1976 sh.flag.update == S_TRUE)
1977 sh_hash_pushdata_memory (&tmpFile, SH_KEY_NULL);
1978 else
1979 sh_hash_pushdata (&tmpFile, SH_KEY_NULL);
1980
1981 return;
1982}
1983
1984extern int sh_util_hextobinary (char * binary, char * hex, int bytes);
1985
1986char * sh_hash_db2pop (char * key, unsigned long * val1,
1987 unsigned long * val2, unsigned long * val3,
1988 int * size)
1989{
1990 file_type tmpFile;
1991 size_t len;
1992 char * p;
1993 int i;
1994
1995 *size = 0;
1996
1997 if (0 == sh_hash_get_it (key, &tmpFile))
1998 {
1999 *val1 = tmpFile.size;
2000 *val2 = tmpFile.mtime;
2001 *val3 = tmpFile.ctime;
2002
2003 if (tmpFile.linkpath[0] != '-')
2004 {
2005 len = strlen(tmpFile.linkpath);
2006
2007 p = SH_ALLOC((len/2)+1);
2008 i = sh_util_hextobinary (p, tmpFile.linkpath, len);
2009
2010 if (i == 0)
2011 {
2012 *size = (len/2);
2013 p[*size] = '\0';
2014 return p;
2015 }
2016 else
2017 {
2018 SH_FREE(p);
2019 *size = 0;
2020 return NULL;
2021 }
2022 }
2023 else
2024 {
2025 *size = 0;
2026 return NULL;
2027 }
2028 }
2029 else
2030 {
2031 *size = -1;
2032 *val1 = 0;
2033 *val2 = 0;
2034 *val3 = 0;
2035 return NULL;
2036 }
2037}
2038
2039
2040
2041
2042/******************************************************************
2043 *
2044 * Data entry in hash table
2045 *
2046 ******************************************************************/
2047sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
2048{
2049 sh_file_t * fp;
2050 sh_filestore_t p;
2051
2052 size_t len;
2053 char * fullpath;
2054 char * linkpath;
2055 char * attr_string = NULL;
2056
2057 SL_ENTER(_("sh_hash_push_int"));
2058
2059 fp = SH_ALLOC(sizeof(sh_file_t));
2060
2061 p.mark = REC_MAGIC;
2062 if (buf->attr_string)
2063 p.mark |= REC_FLAGS_ATTR;
2064 sl_strlcpy(p.c_mode, buf->c_mode, 11);
2065 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
2066 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
2067 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
2068#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2069 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
2070#endif
2071
2072#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2073 p.attributes = (UINT32) buf->attributes;
2074#endif
2075 p.linkmode = (UINT32) buf->linkmode;
2076 p.hardlinks = (UINT32) buf->hardlinks;
2077 p.dev = (UINT64) buf->dev;
2078 p.rdev = (UINT64) buf->rdev;
2079 p.mode = (UINT32) buf->mode;
2080 p.ino = (UINT32) buf->ino;
2081 p.size = (UINT64) buf->size;
2082 p.mtime = (UINT64) buf->mtime;
2083 p.atime = (UINT64) buf->atime;
2084 p.ctime = (UINT64) buf->ctime;
2085 p.owner = (UINT32) buf->owner;
2086 p.group = (UINT32) buf->group;
2087
2088 memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
2089 fp->visited = S_FALSE;
2090 fp->reported = S_FALSE;
2091 fp->allignore = S_FALSE;
2092 fp->modi_mask = 0L;
2093
2094 if (buf->attr_string)
2095 attr_string = sh_util_strdup(buf->attr_string);
2096 fp->attr_string = attr_string;
2097
2098 len = sl_strlen(buf->fullpath);
2099 if (len <= MAX_PATH_STORE)
2100 {
2101 fullpath = SH_ALLOC(len+1);
2102 sl_strlcpy(fullpath, buf->fullpath, len+1);
2103 }
2104 else
2105 {
2106 fullpath = SH_ALLOC(KEY_LEN + 1);
2107 sl_strlcpy(fullpath,
2108 sh_tiger_hash (buf->fullpath, TIGER_DATA, len),
2109 KEY_LEN+1);
2110 }
2111 fp->fullpath = fullpath;
2112
2113 if (buf->c_mode[0] == 'l')
2114 {
2115 len = sl_strlen(buf->linkpath);
2116 if (len <= MAX_PATH_STORE)
2117 {
2118 linkpath = SH_ALLOC(len+1);
2119 sl_strlcpy(linkpath, buf->linkpath, len+1);
2120 }
2121 else
2122 {
2123 linkpath = SH_ALLOC(KEY_LEN + 1);
2124 sl_strlcpy(linkpath,
2125 sh_tiger_hash (buf->linkpath, TIGER_DATA, len),
2126 KEY_LEN+1);
2127 }
2128 fp->linkpath = linkpath;
2129 }
2130 else
2131 fp->linkpath = NULL;
2132
2133 SL_RETURN( fp, _("sh_hash_push_int"));
2134}
2135
2136#ifdef HAVE_INTTYPES_H
2137#include <inttypes.h>
2138#else
2139#ifdef HAVE_STDINT_H
2140#include <stdint.h>
2141#endif
2142#endif
2143
2144#ifndef PRIu64
2145#ifdef HAVE_LONG_32
2146#define PRIu64 "llu"
2147#else
2148#define PRIu64 "lu"
2149#endif
2150#endif
2151
2152char * sh_hash_size_format()
2153{
2154 static char form_rval[81];
2155
2156 SL_ENTER(_("sh_hash_size_format"));
2157
2158
2159#ifdef SH_USE_XML
2160 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2161 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
2162#else
2163 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2164 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
2165#endif
2166
2167 SL_RETURN( form_rval, _("sh_hash_size_format"));
2168}
2169
2170
2171#ifdef SH_USE_XML
2172static char * all_items (file_type * theFile, char * fileHash, int is_new)
2173{
2174 char timstr1c[32];
2175 char timstr1a[32];
2176 char timstr1m[32];
2177
2178 char * tmp_lnk;
2179 char * format;
2180
2181 char * tmp = SH_ALLOC(SH_BUFSIZE);
2182 char * msg = SH_ALLOC(SH_BUFSIZE);
2183
2184 tmp[0] = '\0';
2185 msg[0] = '\0';
2186
2187
2188#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2189 if (is_new)
2190 format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" ");
2191 else
2192 format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" ");
2193 sl_snprintf(tmp, SH_BUFSIZE, format,
2194 theFile->c_mode,
2195 theFile->c_attributes,
2196 (long) theFile->mode,
2197 (long) theFile->attributes
2198 );
2199#else
2200 if (is_new)
2201 format = _("mode_new=\"%s\" imode_new=\"%ld\" ");
2202 else
2203 format = _("mode_old=\"%s\" imode_old=\"%ld\" ");
2204
2205 sl_snprintf(tmp, SH_BUFSIZE, format,
2206 theFile->c_mode,
2207 (long) theFile->mode
2208 );
2209#endif
2210 sl_strlcat(msg, tmp, SH_BUFSIZE);
2211
2212 if (is_new)
2213 format = _("hardlinks_new=\"%lu\" ");
2214 else
2215 format = _("hardlinks_old=\"%lu\" ");
2216 sl_snprintf(tmp, SH_BUFSIZE, format,
2217 (unsigned long) theFile->hardlinks);
2218 sl_strlcat(msg, tmp, SH_BUFSIZE);
2219
2220
2221 if (is_new)
2222 format = _("idevice_new=\"%lu\" ");
2223 else
2224 format = _("idevice_old=\"%lu\" ");
2225 sl_snprintf(tmp, SH_BUFSIZE, format, (unsigned long) theFile->rdev);
2226 sl_strlcat(msg, tmp, SH_BUFSIZE);
2227
2228
2229 if (is_new)
2230 format = _("inode_new=\"%lu\" ");
2231 else
2232 format = _("inode_old=\"%lu\" ");
2233 sl_snprintf(tmp, SH_BUFSIZE, format, (unsigned long) theFile->ino);
2234 sl_strlcat(msg, tmp, SH_BUFSIZE);
2235
2236 /*
2237 * also report device for prelude
2238 */
2239#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
2240 if (is_new)
2241 format = _("dev_new=\"%lu,%lu\" ");
2242 else
2243 format = _("dev_old=\"%lu,%lu\" ");
2244 sl_snprintf(tmp, SH_BUFSIZE, format,
2245 (unsigned long) major(theFile->dev),
2246 (unsigned long) minor(theFile->dev));
2247 sl_strlcat(msg, tmp, SH_BUFSIZE);
2248#endif
2249
2250
2251 if (is_new)
2252 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
2253 else
2254 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
2255 sl_snprintf(tmp, SH_BUFSIZE, format,
2256 theFile->c_owner, (long) theFile->owner);
2257 sl_strlcat(msg, tmp, SH_BUFSIZE);
2258
2259
2260 if (is_new)
2261 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
2262 else
2263 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
2264 sl_snprintf(tmp, SH_BUFSIZE, format,
2265 theFile->c_group, (long) theFile->group);
2266 sl_strlcat(msg, tmp, SH_BUFSIZE);
2267
2268
2269 if (is_new)
2270 sl_snprintf(tmp, SH_BUFSIZE, sh_hash_size_format(),
2271 (UINT64) 0, (UINT64) theFile->size);
2272 else
2273 sl_snprintf(tmp, SH_BUFSIZE, sh_hash_size_format(),
2274 (UINT64) theFile->size, (UINT64) 0);
2275 sl_strlcat(msg, tmp, SH_BUFSIZE);
2276
2277
2278 sl_strlcpy (timstr1c, sh_unix_gmttime (theFile->ctime), 32);
2279 if (is_new)
2280 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_new=\"%s\" "), timstr1c);
2281 else
2282 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_old=\"%s\" "), timstr1c);
2283 sl_strlcat(msg, tmp, SH_BUFSIZE);
2284
2285 sl_strlcpy (timstr1a, sh_unix_gmttime (theFile->atime), 32);
2286 if (is_new)
2287 sl_snprintf(tmp, SH_BUFSIZE, _("atime_new=\"%s\" "), timstr1a);
2288 else
2289 sl_snprintf(tmp, SH_BUFSIZE, _("atime_old=\"%s\" "), timstr1a);
2290 sl_strlcat(msg, tmp, SH_BUFSIZE);
2291
2292 sl_strlcpy (timstr1m, sh_unix_gmttime (theFile->mtime), 32);
2293 if (is_new)
2294 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_new=\"%s\" "), timstr1m);
2295 else
2296 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_old=\"%s\" "), timstr1m);
2297 sl_strlcat(msg, tmp, SH_BUFSIZE);
2298
2299 if (is_new)
2300 sl_snprintf(tmp, SH_BUFSIZE, _("chksum_new=\"%s\" "), fileHash);
2301 else
2302 sl_snprintf(tmp, SH_BUFSIZE, _("chksum_old=\"%s\" "), fileHash);
2303 sl_strlcat(msg, tmp, SH_BUFSIZE);
2304
2305 if (theFile->c_mode[0] == 'l')
2306 {
2307 tmp_lnk = sh_util_safe_name(theFile->linkpath);
2308 if (tmp_lnk)
2309 {
2310 if (is_new)
2311 sl_snprintf(tmp, SH_BUFSIZE, _("link_new=\"%s\" "), tmp_lnk);
2312 else
2313 sl_snprintf(tmp, SH_BUFSIZE, _("link_old=\"%s\" "), tmp_lnk);
2314 SH_FREE(tmp_lnk);
2315 sl_strlcat(msg, tmp, SH_BUFSIZE);
2316 }
2317 }
2318
2319 if (theFile->attr_string)
2320 {
2321 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2322 if (tmp_lnk)
2323 {
2324 if (is_new)
2325 sl_snprintf(tmp, SH_BUFSIZE, _("acl_new=\"%s\" "), tmp_lnk);
2326 else
2327 sl_snprintf(tmp, SH_BUFSIZE, _("acl_old=\"%s\" "), tmp_lnk);
2328 SH_FREE(tmp_lnk);
2329 sl_strlcat(msg, tmp, SH_BUFSIZE);
2330 }
2331 }
2332
2333
2334 SH_FREE(tmp);
2335 return (msg);
2336}
2337#else
2338static char * all_items (file_type * theFile, char * fileHash, int is_new)
2339{
2340 char timstr1c[32];
2341 char timstr1a[32];
2342 char timstr1m[32];
2343
2344 char * tmp_lnk;
2345 char * format;
2346
2347 char * tmp = SH_ALLOC(SH_BUFSIZE);
2348 char * msg = SH_ALLOC(SH_BUFSIZE);
2349
2350 tmp[0] = '\0';
2351 msg[0] = '\0';
2352
2353
2354#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2355 if (is_new)
2356 format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, ");
2357 else
2358 format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, ");
2359 sl_snprintf(tmp, SH_BUFSIZE, format,
2360 theFile->c_mode,
2361 theFile->c_attributes,
2362 (long) theFile->mode,
2363 (long) theFile->attributes
2364 );
2365#else
2366 if (is_new)
2367 format = _("mode_new=<%s>, imode_new=<%ld>, ");
2368 else
2369 format = _("mode_old=<%s>, imode_old=<%ld>, ");
2370
2371 sl_snprintf(tmp, SH_BUFSIZE, format,
2372 theFile->c_mode,
2373 (long) theFile->mode
2374 );
2375#endif
2376 sl_strlcat(msg, tmp, SH_BUFSIZE);
2377
2378 if (is_new)
2379 format = _("hardlinks_new=<%lu>, ");
2380 else
2381 format = _("hardlinks_old=<%lu>, ");
2382 sl_snprintf(tmp, SH_BUFSIZE, format,
2383 (unsigned long) theFile->hardlinks);
2384 sl_strlcat(msg, tmp, SH_BUFSIZE);
2385
2386
2387 if (is_new)
2388 format = _("idevice_new=<%lu>, ");
2389 else
2390 format = _("idevice_old=<%lu>, ");
2391 sl_snprintf(tmp, SH_BUFSIZE, format, (unsigned long) theFile->rdev);
2392 sl_strlcat(msg, tmp, SH_BUFSIZE);
2393
2394
2395 if (is_new)
2396 format = _("inode_new=<%lu>, ");
2397 else
2398 format = _("inode_old=<%lu>, ");
2399 sl_snprintf(tmp, SH_BUFSIZE, format, (unsigned long) theFile->ino);
2400 sl_strlcat(msg, tmp, SH_BUFSIZE);
2401
2402
2403 /*
2404 * also report device for prelude
2405 */
2406#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
2407 if (is_new)
2408 format = _("dev_new=<%lu,%lu>, ");
2409 else
2410 format = _("dev_old=<%lu,%lu>, ");
2411 sl_snprintf(tmp, SH_BUFSIZE, format,
2412 (unsigned long) major(theFile->dev),
2413 (unsigned long) minor(theFile->dev));
2414 sl_strlcat(msg, tmp, SH_BUFSIZE);
2415#endif
2416
2417 if (is_new)
2418 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
2419 else
2420 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
2421 sl_snprintf(tmp, SH_BUFSIZE, format,
2422 theFile->c_owner, (long) theFile->owner);
2423 sl_strlcat(msg, tmp, SH_BUFSIZE);
2424
2425
2426 if (is_new)
2427 format = _("group_new=<%s>, igroup_new=<%ld>, ");
2428 else
2429 format = _("group_old=<%s>, igroup_old=<%ld>, ");
2430 sl_snprintf(tmp, SH_BUFSIZE, format,
2431 theFile->c_group, (long) theFile->group);
2432 sl_strlcat(msg, tmp, SH_BUFSIZE);
2433
2434
2435 if (is_new)
2436 sl_snprintf(tmp, SH_BUFSIZE, sh_hash_size_format(),
2437 (UINT64) 0, (UINT64) theFile->size);
2438 else
2439 sl_snprintf(tmp, SH_BUFSIZE, sh_hash_size_format(),
2440 (UINT64) theFile->size, (UINT64) 0);
2441 sl_strlcat(msg, tmp, SH_BUFSIZE);
2442
2443
2444 sl_strlcpy (timstr1c, sh_unix_gmttime (theFile->ctime), 32);
2445 if (is_new)
2446 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_new=<%s>, "), timstr1c);
2447 else
2448 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_old=<%s>, "), timstr1c);
2449 sl_strlcat(msg, tmp, SH_BUFSIZE);
2450
2451 sl_strlcpy (timstr1a, sh_unix_gmttime (theFile->atime), 32);
2452 if (is_new)
2453 sl_snprintf(tmp, SH_BUFSIZE, _("atime_new=<%s>, "), timstr1a);
2454 else
2455 sl_snprintf(tmp, SH_BUFSIZE, _("atime_old=<%s>, "), timstr1a);
2456 sl_strlcat(msg, tmp, SH_BUFSIZE);
2457
2458 sl_strlcpy (timstr1m, sh_unix_gmttime (theFile->mtime), 32);
2459 if (is_new)
2460 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_new=<%s>, "), timstr1m);
2461 else
2462 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_old=<%s>, "), timstr1m);
2463 sl_strlcat(msg, tmp, SH_BUFSIZE);
2464
2465 if (is_new)
2466 sl_snprintf(tmp, SH_BUFSIZE, _("chksum_new=<%s>"), fileHash);
2467 else
2468 sl_snprintf(tmp, SH_BUFSIZE, _("chksum_old=<%s>"), fileHash);
2469 sl_strlcat(msg, tmp, SH_BUFSIZE);
2470
2471 if (theFile->c_mode[0] == 'l')
2472 {
2473 tmp_lnk = sh_util_safe_name(theFile->linkpath);
2474 if (tmp_lnk)
2475 {
2476 if (is_new)
2477 sl_snprintf(tmp, SH_BUFSIZE, _(", link_new=<%s> "), tmp_lnk);
2478 else
2479 sl_snprintf(tmp, SH_BUFSIZE, _(", link_old=<%s> "), tmp_lnk);
2480 SH_FREE(tmp_lnk);
2481 sl_strlcat(msg, tmp, SH_BUFSIZE);
2482 }
2483 }
2484
2485 if (theFile->attr_string)
2486 {
2487 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2488 if (tmp_lnk)
2489 {
2490 if (is_new)
2491 sl_snprintf(tmp, SH_BUFSIZE, _(", acl_new=<%s> "), tmp_lnk);
2492 else
2493 sl_snprintf(tmp, SH_BUFSIZE, _(", acl_old=<%s> "), tmp_lnk);
2494 SH_FREE(tmp_lnk);
2495 sl_strlcat(msg, tmp, SH_BUFSIZE);
2496 }
2497 }
2498
2499 SH_FREE(tmp);
2500 return (msg);
2501}
2502#endif
2503
2504void sh_hash_pushdata_memory (file_type * theFile, char * fileHash)
2505{
2506 sh_file_t * p;
2507
2508 SL_ENTER(_("sh_hash_pushdata_memory"));
2509
2510 p = sh_hash_push_int(theFile, fileHash);
2511 if (p)
2512 {
2513 hashinsert (p);
2514 p->modi_mask = theFile->check_mask;
2515 }
2516
2517 SL_RET0(_("sh_hash_pushdata_memory"));
2518}
2519
2520
2521/*****************************************************************
2522 *
2523 * Compare a file with the database status.
2524 *
2525 *****************************************************************/
2526int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
2527 char * policy_override, int severity_override)
2528{
2529 char * msg;
2530 sh_file_t * p;
2531 char * tmp;
2532 char * tmp_path;
2533 char * tmp_lnk;
2534 char * tmp_lnk_old;
2535
2536 char * str;
2537
2538 char timstr1c[32];
2539 char timstr2c[32];
2540 char timstr1a[32];
2541 char timstr2a[32];
2542 char timstr1m[32];
2543 char timstr2m[32];
2544 char linkHash[KEY_LEN+1];
2545 int maxcomp;
2546
2547 char change_code[16];
2548 int i;
2549
2550 unsigned long modi_mask = 0;
2551
2552 char log_policy[32];
2553 int log_severity;
2554
2555 SL_ENTER(_("sh_hash_compdata"));
2556
2557 if (IsInit != 1) sh_hash_init();
2558
2559 if (severity_override < 0)
2560 log_severity = ShDFLevel[class];
2561 else
2562 log_severity = severity_override;
2563
2564 if (policy_override != NULL)
2565 sl_strlcpy (log_policy, policy_override, 32);
2566
2567 /* -------- find the entry for the file ---------------- */
2568
2569 if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE)
2570 p = hashsearch(theFile->fullpath);
2571 else
2572 p = hashsearch( sh_tiger_hash(theFile->fullpath,
2573 TIGER_DATA,
2574 sl_strlen(theFile->fullpath))
2575 );
2576
2577
2578 /* --------- Not found in database. ------------
2579 */
2580
2581 if (p == NULL)
2582 {
2583 if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
2584 {
2585 tmp = sh_util_safe_name(theFile->fullpath);
2586
2587 str = all_items (theFile, fileHash, 1);
2588 sh_error_handle (log_severity, FIL__, __LINE__, 0,
2589 MSG_FI_ADD2,
2590 tmp, str);
2591 SH_FREE(str);
2592
2593 SH_FREE(tmp);
2594 }
2595
2596 if (p)
2597 p->visited = S_TRUE;
2598 if (sh.flag.reportonce == S_TRUE)
2599 theFile->reported = S_TRUE;
2600
2601 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2602 {
2603 p = sh_hash_push_int(theFile, fileHash);
2604 hashinsert (p);
2605 if (p)
2606 p->modi_mask = theFile->check_mask;
2607 }
2608
2609 else if (S_TRUE == sh.flag.update)
2610 {
2611 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
2612 {
2613 p = sh_hash_push_int(theFile, fileHash);
2614 hashinsert (p);
2615 if (p)
2616 p->modi_mask = theFile->check_mask;
2617 }
2618 else
2619 {
2620 SL_RETURN(1, _("sh_hash_compdata"));
2621 }
2622 }
2623
2624 SL_RETURN(0, _("sh_hash_compdata"));
2625 }
2626 else
2627 {
2628 p->modi_mask = theFile->check_mask;
2629 }
2630
2631 /* initialize change_code */
2632 for (i = 0; i < 15; ++i)
2633 change_code[i] = '-';
2634 change_code[15] = '\0';
2635
2636 TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"),
2637 theFile->fullpath, fileHash, p->theFile.checksum));
2638
2639 if ( (fileHash != NULL) && (p->theFile.checksum != NULL) &&
2640 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
2641 (theFile->check_mask & MODI_CHK) != 0)
2642 {
2643 if ((theFile->check_mask & MODI_SGROW) == 0)
2644 {
2645 modi_mask |= MODI_CHK;
2646 change_code[0] = 'C';
2647 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
2648 }
2649 else
2650 {
2651 if (0 != strncmp (&fileHash[KEY_LEN + 1],
2652 p->theFile.checksum, KEY_LEN))
2653 {
2654 modi_mask |= MODI_CHK;
2655 change_code[0] = 'C';
2656 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
2657 }
2658 else
2659 {
2660 p->theFile.size = theFile->size;
2661 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2662 }
2663 }
2664 }
2665
2666 if (p->theFile.c_mode[0] == 'l')
2667 {
2668 if (sl_strlen(theFile->linkpath) >= MAX_PATH_STORE)
2669 {
2670 sl_strlcpy(linkHash,
2671 sh_tiger_hash(theFile->linkpath,
2672 TIGER_DATA,
2673 sl_strlen(theFile->linkpath)),
2674 MAX_PATH_STORE+1);
2675 maxcomp = MAX_PATH_STORE;
2676 }
2677 else
2678 {
2679 sl_strlcpy(linkHash, theFile->linkpath, KEY_LEN + 1);
2680 maxcomp = KEY_LEN;
2681 }
2682
2683
2684 if ( sl_strncmp (linkHash, p->linkpath, maxcomp) != 0 &&
2685 (theFile->check_mask & MODI_LNK) != 0)
2686 {
2687 modi_mask |= MODI_LNK;
2688 change_code[1] = 'L';
2689 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2690 }
2691 }
2692
2693 if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b')
2694 {
2695 if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) ||
2696 minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
2697 (theFile->check_mask & MODI_RDEV) != 0)
2698 {
2699 modi_mask |= MODI_RDEV;
2700 change_code[2] = 'D';
2701 TPT ((0, FIL__, __LINE__, _("mod=<rdev>")));
2702 }
2703 }
2704
2705 /* cast to UINT32 in case ino_t is not 32bit
2706 */
2707 if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino &&
2708 (theFile->check_mask & MODI_INO) != 0)
2709 {
2710 modi_mask |= MODI_INO;
2711 change_code[3] = 'I';
2712 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2713 }
2714
2715 if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
2716 (theFile->check_mask & MODI_HLN) != 0)
2717 {
2718 modi_mask |= MODI_HLN;
2719 change_code[4] = 'H';
2720 TPT ((0, FIL__, __LINE__, _("mod=<hardlink>")));
2721 }
2722
2723
2724 if ( ( (theFile->mode != p->theFile.mode)
2725#if defined(USE_ACL) || defined(USE_XATTR)
2726 || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
2727 (
2728 (theFile->attr_string == NULL && p->attr_string != NULL) ||
2729 (theFile->attr_string != NULL && p->attr_string == NULL) ||
2730 (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
2731 )
2732 )
2733#endif
2734#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2735 || (theFile->attributes != p->theFile.attributes)
2736#endif
2737 )
2738 && (theFile->check_mask & MODI_MOD) != 0)
2739 {
2740 modi_mask |= MODI_MOD;
2741 change_code[5] = 'M';
2742 TPT ((0, FIL__, __LINE__, _("mod=<mode>")));
2743 /*
2744 * report link path if switch link/no link
2745 */
2746 if ((theFile->check_mask & MODI_LNK) != 0 &&
2747 (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
2748 (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
2749 {
2750 modi_mask |= MODI_LNK;
2751 change_code[1] = 'L';
2752 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2753 }
2754 }
2755
2756 if ( theFile->owner != (uid_t) p->theFile.owner &&
2757 (theFile->check_mask & MODI_USR) != 0)
2758 {
2759 modi_mask |= MODI_USR;
2760 change_code[6] = 'U';
2761 TPT ((0, FIL__, __LINE__, _("mod=<user>")));
2762 }
2763
2764 if ( theFile->group != (gid_t) p->theFile.group &&
2765 (theFile->check_mask & MODI_GRP) != 0)
2766 {
2767 modi_mask |= MODI_GRP;
2768 change_code[7] = 'G';
2769 TPT ((0, FIL__, __LINE__, _("mod=<group>")));
2770 }
2771
2772
2773 if ( theFile->mtime != (time_t) p->theFile.mtime &&
2774 (theFile->check_mask & MODI_MTM) != 0)
2775 {
2776 modi_mask |= MODI_MTM;
2777 change_code[8] = 'T';
2778 TPT ((0, FIL__, __LINE__, _("mod=<mtime>")));
2779 }
2780
2781 if ( (theFile->check_mask & MODI_ATM) != 0 &&
2782 theFile->atime != (time_t) p->theFile.atime)
2783 {
2784 modi_mask |= MODI_ATM;
2785 change_code[8] = 'T';
2786 TPT ((0, FIL__, __LINE__, _("mod=<atime>")));
2787 }
2788
2789
2790 /* Resetting the access time will set a new ctime. Thus, either we ignore
2791 * the access time or the ctime for NOIGNORE
2792 */
2793 if ( theFile->ctime != (time_t) p->theFile.ctime &&
2794 (theFile->check_mask & MODI_CTM) != 0)
2795 {
2796 modi_mask |= MODI_CTM;
2797 change_code[8] = 'T';
2798 TPT ((0, FIL__, __LINE__, _("mod=<ctime>")));
2799 }
2800
2801 if ( theFile->size != (off_t) p->theFile.size &&
2802 (theFile->check_mask & MODI_SIZ) != 0)
2803 {
2804 if ((theFile->check_mask & MODI_SGROW) == 0 ||
2805 theFile->size < (off_t) p->theFile.size)
2806 {
2807 modi_mask |= MODI_SIZ;
2808 change_code[9] = 'S';
2809 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
2810 }
2811 }
2812 change_code[10] = '\0';
2813
2814 /* --- Report full details. ---
2815 */
2816 if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
2817 {
2818 if ((theFile->check_mask & MODI_ATM) == 0)
2819 modi_mask = MASK_READONLY_;
2820 else
2821 modi_mask = MASK_NOIGNORE_;
2822 }
2823
2824 /* --- Report on modified files. ---
2825 */
2826 if (modi_mask != 0 && p->reported == S_FALSE)
2827 {
2828 tmp = SH_ALLOC(SH_BUFSIZE);
2829 msg = SH_ALLOC(SH_BUFSIZE);
2830 msg[0] = '\0';
2831
2832 if ( ((modi_mask & MODI_MOD) != 0)
2833#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
2834 || ((modi_mask & MODI_USR) != 0)
2835 || ((modi_mask & MODI_GRP) != 0)
2836#endif
2837 )
2838 {
2839#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2840 sl_snprintf(tmp, SH_BUFSIZE,
2841#ifdef SH_USE_XML
2842 _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "),
2843#else
2844 _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "),
2845#endif
2846 p->theFile.c_mode, theFile->c_mode,
2847 p->theFile.c_attributes, theFile->c_attributes
2848#ifdef SH_USE_XML
2849 , (long) p->theFile.mode, (long) theFile->mode,
2850 (long) p->theFile.attributes,
2851 (long) theFile->attributes
2852#endif
2853 );
2854#else
2855#ifdef SH_USE_XML
2856 sl_snprintf(tmp, SH_BUFSIZE,
2857 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
2858 p->theFile.c_mode, theFile->c_mode,
2859 (long) p->theFile.mode, (long) theFile->mode);
2860#else
2861 sl_snprintf(tmp, SH_BUFSIZE, _("mode_old=<%s>, mode_new=<%s>, "),
2862 p->theFile.c_mode, theFile->c_mode);
2863#endif
2864#endif
2865 sl_strlcat(msg, tmp, SH_BUFSIZE);
2866
2867#if defined(USE_ACL) || defined(USE_XATTR)
2868 if (theFile->attr_string != NULL || p->attr_string != NULL)
2869 {
2870 sl_snprintf(tmp, SH_BUFSIZE,
2871#ifdef SH_USE_XML
2872 _("acl_old=\"%s\" acl_new=\"%s\" "),
2873#else
2874 _("acl_old=<%s>, acl_new=<%s>, "),
2875#endif
2876 (p->attr_string) ? p->attr_string : _("none"),
2877 (theFile->attr_string) ? theFile->attr_string : _("none"));
2878
2879 sl_strlcat(msg, tmp, SH_BUFSIZE);
2880 }
2881#endif
2882
2883#ifdef REPLACE_OLD
2884 if ((modi_mask & MODI_MOD) != 0)
2885 {
2886 /*
2887 * We postpone update if sh.flag.update == S_TRUE because
2888 * in interactive mode the user may not accept the change.
2889 */
2890 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2891 {
2892 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
2893 p->theFile.mode = theFile->mode;
2894#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2895 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
2896 p->theFile.attributes = theFile->attributes;
2897#endif
2898#if defined(USE_ACL) || defined(USE_XATTR)
2899 if (p->attr_string == NULL && theFile->attr_string != NULL)
2900 { p->attr_string = sh_util_strdup (theFile->attr_string); }
2901 else if (p->attr_string != NULL && theFile->attr_string == NULL)
2902 { SH_FREE(p->attr_string); p->attr_string = NULL; }
2903 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2904 {
2905 if (0 != strcmp(theFile->attr_string, p->attr_string))
2906 {
2907 SH_FREE(p->attr_string);
2908 p->attr_string = sh_util_strdup (theFile->attr_string);
2909 }
2910 }
2911#endif
2912 }
2913 }
2914#endif
2915 }
2916
2917 if ((modi_mask & MODI_HLN) != 0)
2918 {
2919 sl_snprintf(tmp, SH_BUFSIZE,
2920#ifdef SH_USE_XML
2921 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
2922#else
2923 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
2924#endif
2925 (unsigned long) p->theFile.hardlinks,
2926 (unsigned long) theFile->hardlinks);
2927 sl_strlcat(msg, tmp, SH_BUFSIZE);
2928#ifdef REPLACE_OLD
2929 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2930 p->theFile.hardlinks = theFile->hardlinks;
2931#endif
2932 }
2933
2934 if ((modi_mask & MODI_RDEV) != 0)
2935 {
2936 sl_snprintf(tmp, SH_BUFSIZE,
2937#ifdef SH_USE_XML
2938 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
2939#else
2940 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
2941#endif
2942 (unsigned long) major(p->theFile.rdev),
2943 (unsigned long) minor(p->theFile.rdev),
2944 (unsigned long) major(theFile->rdev),
2945 (unsigned long) minor(theFile->rdev)
2946#ifdef SH_USE_XML
2947 , (unsigned long) p->theFile.rdev,
2948 (unsigned long) theFile->rdev
2949#endif
2950 );
2951 sl_strlcat(msg, tmp, SH_BUFSIZE);
2952#ifdef REPLACE_OLD
2953 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2954 p->theFile.rdev = theFile->rdev;
2955#endif
2956 }
2957
2958 if ((modi_mask & MODI_INO) != 0)
2959 {
2960 sl_snprintf(tmp, SH_BUFSIZE,
2961#ifdef SH_USE_XML
2962 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
2963#else
2964 _("inode_old=<%lu>, inode_new=<%lu>, "),
2965#endif
2966 (unsigned long) p->theFile.ino,
2967 (unsigned long) theFile->ino);
2968 sl_strlcat(msg, tmp, SH_BUFSIZE);
2969#ifdef REPLACE_OLD
2970 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2971 {
2972 p->theFile.ino = theFile->ino;
2973 p->theFile.dev = theFile->dev;
2974 }
2975#endif
2976 }
2977
2978
2979 /*
2980 * also report device for prelude
2981 */
2982#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
2983 if ((modi_mask & MODI_INO) != 0)
2984 {
2985 sl_snprintf(tmp, SH_BUFSIZE,
2986#ifdef SH_USE_XML
2987 _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "),
2988#else
2989 _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "),
2990#endif
2991 (unsigned long) major(p->theFile.dev),
2992 (unsigned long) minor(p->theFile.dev),
2993 (unsigned long) major(theFile->dev),
2994 (unsigned long) minor(theFile->dev)
2995 );
2996 sl_strlcat(msg, tmp, SH_BUFSIZE);
2997#ifdef REPLACE_OLD
2998 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2999 p->theFile.dev = theFile->dev;
3000#endif
3001 }
3002#endif
3003
3004 if ( ((modi_mask & MODI_USR) != 0)
3005#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
3006 || ((modi_mask & MODI_MOD) != 0)
3007#endif
3008 )
3009 {
3010#ifdef SH_USE_XML
3011 sl_snprintf(tmp, SH_BUFSIZE,
3012 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
3013#else
3014 sl_snprintf(tmp, SH_BUFSIZE,
3015 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
3016#endif
3017 p->theFile.c_owner, theFile->c_owner,
3018 (long) p->theFile.owner, (long) theFile->owner
3019 );
3020 sl_strlcat(msg, tmp, SH_BUFSIZE);
3021#ifdef REPLACE_OLD
3022 if ((modi_mask & MODI_USR) != 0) {
3023 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3024 {
3025 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3026 p->theFile.owner = theFile->owner;
3027 }
3028 }
3029#endif
3030 }
3031
3032 if ( ((modi_mask & MODI_GRP) != 0)
3033#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
3034 || ((modi_mask & MODI_MOD) != 0)
3035#endif
3036 )
3037 {
3038#ifdef SH_USE_XML
3039 sl_snprintf(tmp, SH_BUFSIZE,
3040 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
3041 p->theFile.c_group, theFile->c_group,
3042 (long) p->theFile.group, (long) theFile->group);
3043#else
3044 sl_snprintf(tmp, SH_BUFSIZE,
3045 _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "),
3046 p->theFile.c_group, theFile->c_group,
3047 (long) p->theFile.group, (long) theFile->group);
3048#endif
3049
3050 sl_strlcat(msg, tmp, SH_BUFSIZE);
3051#ifdef REPLACE_OLD
3052 if ((modi_mask & MODI_GRP) != 0) {
3053 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3054 {
3055 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3056 p->theFile.group = theFile->group;
3057 }
3058 }
3059#endif
3060 }
3061
3062 if ((modi_mask & MODI_SIZ) != 0)
3063 {
3064 sl_snprintf(tmp, SH_BUFSIZE, sh_hash_size_format(),
3065 (UINT64) p->theFile.size,
3066 (UINT64) theFile->size);
3067 sl_strlcat(msg, tmp, SH_BUFSIZE);
3068#ifdef REPLACE_OLD
3069 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3070 p->theFile.size = theFile->size;
3071#endif
3072 }
3073
3074 if ((modi_mask & MODI_CTM) != 0)
3075 {
3076 sl_strlcpy (timstr1c, sh_unix_gmttime (p->theFile.ctime), 32);
3077 sl_strlcpy (timstr2c, sh_unix_gmttime (theFile->ctime), 32);
3078#ifdef SH_USE_XML
3079 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
3080 timstr1c, timstr2c);
3081#else
3082 sl_snprintf(tmp, SH_BUFSIZE, _("ctime_old=<%s>, ctime_new=<%s>, "),
3083 timstr1c, timstr2c);
3084#endif
3085 sl_strlcat(msg, tmp, SH_BUFSIZE);
3086#ifdef REPLACE_OLD
3087 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3088 p->theFile.ctime = theFile->ctime;
3089#endif
3090 }
3091
3092 if ((modi_mask & MODI_ATM) != 0)
3093 {
3094 sl_strlcpy (timstr1a, sh_unix_gmttime (p->theFile.atime), 32);
3095 sl_strlcpy (timstr2a, sh_unix_gmttime (theFile->atime), 32);
3096#ifdef SH_USE_XML
3097 sl_snprintf(tmp, SH_BUFSIZE, _("atime_old=\"%s\" atime_new=\"%s\" "),
3098 timstr1a, timstr2a);
3099#else
3100 sl_snprintf(tmp, SH_BUFSIZE, _("atime_old=<%s>, atime_new=<%s>, "),
3101 timstr1a, timstr2a);
3102#endif
3103 sl_strlcat(msg, tmp, SH_BUFSIZE);
3104#ifdef REPLACE_OLD
3105 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3106 p->theFile.atime = theFile->atime;
3107#endif
3108 }
3109
3110 if ((modi_mask & MODI_MTM) != 0)
3111 {
3112 sl_strlcpy (timstr1m, sh_unix_gmttime (p->theFile.mtime), 32);
3113 sl_strlcpy (timstr2m, sh_unix_gmttime (theFile->mtime), 32);
3114#ifdef SH_USE_XML
3115 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
3116 timstr1m, timstr2m);
3117#else
3118 sl_snprintf(tmp, SH_BUFSIZE, _("mtime_old=<%s>, mtime_new=<%s>, "),
3119 timstr1m, timstr2m);
3120#endif
3121 sl_strlcat(msg, tmp, SH_BUFSIZE);
3122#ifdef REPLACE_OLD
3123 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3124 p->theFile.mtime = theFile->mtime;
3125#endif
3126 }
3127
3128
3129 if ((modi_mask & MODI_CHK) != 0)
3130 {
3131 sl_snprintf(tmp, SH_BUFSIZE,
3132#ifdef SH_USE_XML
3133 _("chksum_old=\"%s\" chksum_new=\"%s\" "),
3134#else
3135 _("chksum_old=<%s>, chksum_new=<%s>, "),
3136#endif
3137 p->theFile.checksum, fileHash);
3138 sl_strlcat(msg, tmp, SH_BUFSIZE);
3139#ifdef REPLACE_OLD
3140 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3141 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3142#endif
3143 }
3144
3145
3146 if ((modi_mask & MODI_LNK) != 0 && theFile->c_mode[0] == 'l')
3147 {
3148 tmp_lnk = sh_util_safe_name(theFile->linkpath);
3149 tmp_lnk_old = sh_util_safe_name(p->linkpath);
3150#ifdef SH_USE_XML
3151 sl_snprintf(tmp, SH_BUFSIZE, _("link_old=\"%s\" link_new=\"%s\" "),
3152 tmp_lnk_old, tmp_lnk);
3153#else
3154 sl_snprintf(tmp, SH_BUFSIZE, _("link_old=<%s>, link_new=<%s>"),
3155 tmp_lnk_old, tmp_lnk);
3156#endif
3157 SH_FREE(tmp_lnk);
3158 SH_FREE(tmp_lnk_old);
3159 sl_strlcat(msg, tmp, SH_BUFSIZE);
3160#ifdef REPLACE_OLD
3161 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3162 {
3163 if (p->linkpath != NULL)
3164 SH_FREE(p->linkpath);
3165 p->linkpath = sh_util_strdup(theFile->linkpath);
3166 }
3167#endif
3168 }
3169
3170
3171 tmp_path = sh_util_safe_name(theFile->fullpath);
3172 sh_error_handle(log_severity, FIL__, __LINE__,
3173 (long) modi_mask, MSG_FI_CHAN,
3174 (policy_override == NULL) ? _(policy[class]):log_policy,
3175 change_code, tmp_path, msg);
3176
3177 SH_FREE(tmp_path);
3178 SH_FREE(tmp);
3179 SH_FREE(msg);
3180
3181#ifndef REPLACE_OLD
3182 p->reported = S_TRUE;
3183#endif
3184
3185 if (S_TRUE == sh.flag.update)
3186 {
3187 if (S_FALSE == sh_util_ask_update(theFile->fullpath))
3188 {
3189 /* user does not want to update, thus we replace
3190 * with data from the baseline database
3191 */
3192 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
3193 theFile->mode = p->theFile.mode;
3194#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3195 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
3196 theFile->attributes = p->theFile.attributes;
3197#endif
3198#if defined(USE_ACL) || defined(USE_XATTR)
3199 if (theFile->attr_string == NULL && p->attr_string != NULL)
3200 { theFile->attr_string = sh_util_strdup (p->attr_string); }
3201 else if (theFile->attr_string != NULL && p->attr_string == NULL)
3202 { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
3203 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3204 {
3205 if (0 != strcmp(theFile->attr_string, p->attr_string))
3206 {
3207 SH_FREE(theFile->attr_string);
3208 theFile->attr_string = sh_util_strdup (p->attr_string);
3209 }
3210 }
3211#endif
3212
3213 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
3214 {
3215 sl_strlcpy(theFile->linkpath, p->linkpath, PATH_MAX);
3216 }
3217 else
3218 {
3219 theFile->linkpath[0] = '-';
3220 theFile->linkpath[1] = '\0';
3221 }
3222
3223 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
3224
3225 theFile->mtime = p->theFile.mtime;
3226 theFile->ctime = p->theFile.ctime;
3227 theFile->atime = p->theFile.atime;
3228
3229 theFile->size = p->theFile.size;
3230
3231 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
3232 theFile->group = p->theFile.group;
3233 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
3234 theFile->owner = p->theFile.owner;
3235
3236 theFile->ino = p->theFile.ino;
3237 theFile->rdev = p->theFile.rdev;
3238 theFile->dev = p->theFile.dev;
3239 theFile->hardlinks = p->theFile.hardlinks;
3240
3241 p->visited = S_TRUE;
3242 SL_RETURN(1, _("sh_hash_compdata"));
3243 }
3244 else /* if (sh.flag.reportonce == S_TRUE) */
3245 {
3246 /* we replace the data in the in-memory copy of the
3247 * baseline database, because otherwise we would get
3248 * another warning if the suidcheck runs
3249 */
3250 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3251 p->theFile.mode = theFile->mode;
3252#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3253 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
3254 p->theFile.attributes = theFile->attributes;
3255#endif
3256#if defined(USE_ACL) || defined(USE_XATTR)
3257 if (p->attr_string == NULL && theFile->attr_string != NULL)
3258 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3259 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3260 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3261 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3262 {
3263 if (0 != strcmp(theFile->attr_string, p->attr_string))
3264 {
3265 SH_FREE(p->attr_string);
3266 p->attr_string = sh_util_strdup (theFile->attr_string);
3267 }
3268 }
3269#endif
3270
3271 if (theFile->c_mode[0] == 'l')
3272 {
3273 if (p->linkpath != NULL)
3274 SH_FREE(p->linkpath);
3275 p->linkpath = sh_util_strdup(theFile->linkpath);
3276 }
3277 else
3278 {
3279 if (p->linkpath != NULL) {
3280 p->linkpath[0] = '-';
3281 p->linkpath[1] = '\0';
3282 } else {
3283 p->linkpath = SH_ALLOC(2);
3284 p->linkpath[0] = '-';
3285 p->linkpath[1] = '\0';
3286 }
3287 }
3288
3289 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3290
3291 p->theFile.mtime = theFile->mtime;
3292 p->theFile.ctime = theFile->ctime;
3293 p->theFile.atime = theFile->atime;
3294
3295 p->theFile.size = theFile->size;
3296
3297 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3298 p->theFile.group = theFile->group;
3299 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3300 p->theFile.owner = theFile->owner;
3301
3302 p->theFile.ino = theFile->ino;
3303 p->theFile.rdev = theFile->rdev;
3304 p->theFile.dev = theFile->dev;
3305 p->theFile.hardlinks = theFile->hardlinks;
3306 }
3307 }
3308 }
3309
3310 p->visited = S_TRUE;
3311
3312 SL_RETURN(0, _("sh_hash_compdata"));
3313}
3314
3315int hash_full_tree ()
3316{
3317 sh_file_t * p;
3318 int i;
3319
3320 SL_ENTER(_("sh_hash_compdata"));
3321
3322 if (IsInit != 1)
3323 SL_RETURN(0, _("sh_hash_compdata"));
3324
3325 for (i = 0; i < TABSIZE; ++i)
3326 {
3327 for (p = tab[i]; p; p = p->next)
3328 p->allignore = S_FALSE;
3329 }
3330 SL_RETURN (0, _("sh_hash_compdata"));
3331}
3332
3333
3334int hash_remove_tree (char * s)
3335{
3336 sh_file_t * p;
3337 size_t len;
3338 unsigned int i;
3339
3340 SL_ENTER(_("hash_remove_tree"));
3341
3342 if (!s || *s == '\0')
3343 SL_RETURN ((-1), _("hash_remove_tree"));
3344
3345 len = sl_strlen(s);
3346
3347 if (IsInit != 1)
3348 sh_hash_init();
3349
3350 for (i = 0; i < TABSIZE; ++i)
3351 {
3352 for (p = tab[i]; p; p = p->next)
3353 {
3354 if (p->fullpath && 0 == strncmp(s, p->fullpath, len))
3355 {
3356 p->allignore = S_TRUE;
3357 }
3358 }
3359 }
3360 SL_RETURN ((0), _("hash_remove_tree"));
3361}
3362
3363#if TIME_WITH_SYS_TIME
3364#include <sys/time.h>
3365#include <time.h>
3366#else
3367#if HAVE_SYS_TIME_H
3368#include <sys/time.h>
3369#else
3370#include <time.h>
3371#endif
3372#endif
3373
3374static int ListFullDetail = S_FALSE;
3375static int ListWithDelimiter = S_FALSE;
3376
3377int set_full_detail (const char * c)
3378{
3379 ListFullDetail = S_TRUE;
3380 /* warning: unused parameter `c' */
3381 if (c)
3382 return 0;
3383 else
3384 return 0;
3385}
3386
3387int set_list_delimited (const char * c)
3388{
3389 ListFullDetail = S_TRUE;
3390 ListWithDelimiter = S_TRUE;
3391 /* warning: unused parameter `c' */
3392 if (c)
3393 return 0;
3394 else
3395 return 0;
3396}
3397
3398/* Always quote the string, except if it is empty. Qoute quotes by
3399 * doubling them.
3400 */
3401char * csv_escape(const char * str)
3402{
3403 const char * p = str;
3404 const char * q;
3405
3406 size_t size = 0;
3407 size_t flag_quote = 0;
3408 int flag_comma = 0;
3409 char * new;
3410 char * pnew;
3411
3412 if (p)
3413 {
3414
3415 while (*p)
3416 {
3417 if (*p == ',')
3418 flag_comma = 1;
3419 else if (*p == '"')
3420 ++flag_quote;
3421
3422 ++size; ++p;
3423 }
3424
3425 if (sl_ok_adds(size, flag_quote))
3426 size += flag_quote; /* double each quote */
3427 else
3428 return NULL;
3429
3430 if (sl_ok_adds(size, 3))
3431 size += 3; /* two quotes and terminating null */
3432 else
3433 return NULL;
3434
3435 new = SH_ALLOC(size);
3436
3437 if (flag_quote != 0)
3438 {
3439 new[0] = '"';
3440 pnew = &new[1];
3441 q = str;
3442 while (*q)
3443 {
3444 *pnew = *q;
3445 if (*pnew == '"')
3446 {
3447 ++pnew; *pnew = '"';
3448 }
3449 ++pnew; ++q;
3450 }
3451 *pnew = '"'; ++pnew;
3452 *pnew = '\0';
3453 }
3454 else
3455 {
3456 if (size > 3)
3457 {
3458 new[0] = '"';
3459 sl_strlcpy (&new[1], str, size-1);
3460 new[size-2] = '"';
3461 new[size-1] = '\0';
3462 }
3463 else
3464 {
3465 new[0] = '\0';
3466 }
3467 }
3468
3469 return new;
3470 }
3471 return NULL;
3472}
3473
3474
3475
3476void sh_hash_list_db_entry_full_detail (sh_file_t * p)
3477{
3478 char * tmp;
3479 char * esc;
3480 char str[81];
3481
3482 if (ListWithDelimiter == S_TRUE)
3483 {
3484 printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "),
3485 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3486 p->theFile.c_mode, (int) p->theFile.mode,
3487 p->theFile.c_attributes, (int) p->theFile.attributes,
3488 (int) p->theFile.hardlinks,
3489 p->theFile.c_owner, (int) p->theFile.owner,
3490 p->theFile.c_group, (int) p->theFile.group);
3491 }
3492 else
3493 {
3494 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
3495 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3496 p->theFile.c_mode, (int) p->theFile.mode,
3497 p->theFile.c_attributes, (int) p->theFile.attributes,
3498 (int) p->theFile.hardlinks,
3499 p->theFile.c_owner, (int) p->theFile.owner,
3500 p->theFile.c_group, (int) p->theFile.group);
3501 }
3502
3503 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3504 sl_snprintf(str, 80, "%"PRIu64, p->theFile.rdev);
3505 else
3506 sl_snprintf(str, 80, "%"PRIu64, p->theFile.size);
3507
3508 printf( _(" %8s"), str);
3509 if (ListWithDelimiter == S_TRUE)
3510 putchar(',');
3511
3512 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime));
3513 if (ListWithDelimiter == S_TRUE)
3514 putchar(',');
3515 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime));
3516 if (ListWithDelimiter == S_TRUE)
3517 putchar(',');
3518 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime));
3519 if (ListWithDelimiter == S_TRUE)
3520 putchar(',');
3521 printf( _(" %s"), p->theFile.checksum);
3522 if (ListWithDelimiter == S_TRUE)
3523 putchar(',');
3524
3525 tmp = sh_util_safe_name(p->fullpath);
3526 if (ListWithDelimiter != S_TRUE)
3527 {
3528 printf( _(" %s"), tmp);
3529 }
3530 else
3531 {
3532 esc = csv_escape(tmp);
3533 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3534 if (esc)
3535 SH_FREE(esc);
3536 }
3537 SH_FREE(tmp);
3538
3539 if ('l' == p->theFile.c_mode[0])
3540 {
3541 tmp = sh_util_safe_name(p->linkpath);
3542 if (ListWithDelimiter != S_TRUE)
3543 {
3544 printf(_(" -> %s"), tmp);
3545 }
3546 else
3547 {
3548 esc = csv_escape(tmp);
3549 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3550 if (esc)
3551 SH_FREE(esc);
3552 }
3553 SH_FREE(tmp);
3554 }
3555
3556 if (p->attr_string)
3557 {
3558 tmp = sh_util_safe_name(p->attr_string);
3559 if (ListWithDelimiter != S_TRUE)
3560 {
3561 printf(_(" %s"), tmp);
3562 }
3563 else
3564 {
3565 esc = csv_escape(tmp);
3566 printf( _(" %s"), (esc != NULL) ? esc : _("(null)"));
3567 if (esc)
3568 SH_FREE(esc);
3569 }
3570 printf(_(" %s"), tmp);
3571 SH_FREE(tmp);
3572 }
3573 else
3574 {
3575 if (ListWithDelimiter == S_TRUE)
3576 printf(_(" no_attr"));
3577 }
3578 putchar('\n');
3579
3580 return;
3581}
3582
3583void sh_hash_list_db_entry (sh_file_t * p)
3584{
3585 char nowtime[128];
3586 char thetime[128];
3587 char * tmp;
3588 time_t now = time(NULL);
3589 time_t then = (time_t) p->theFile.mtime;
3590
3591 strftime(thetime, 127, _("%b %d %Y"), gmtime(&then));
3592 strftime(nowtime, 127, _("%b %d %Y"), gmtime(&now));
3593 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3594 strftime(thetime, 127, _("%b %d %H:%M"), gmtime(&then));
3595
3596 tmp = sh_util_safe_name(p->fullpath);
3597 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3598 printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"),
3599 p->theFile.c_mode, (int) p->theFile.hardlinks,
3600 p->theFile.c_owner, p->theFile.c_group,
3601 (int) major((dev_t)p->theFile.rdev),
3602 (int) minor((dev_t)p->theFile.rdev),
3603 thetime,
3604 tmp);
3605 else
3606 printf(_("%10s %3d %-8s %-8s %8ld %s %s"),
3607 p->theFile.c_mode, (int) p->theFile.hardlinks,
3608 p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size,
3609 thetime,
3610 tmp);
3611 SH_FREE(tmp);
3612
3613 if ('l' == p->theFile.c_mode[0])
3614 {
3615 tmp = sh_util_safe_name(p->linkpath);
3616 printf(_(" -> %s\n"), tmp);
3617 SH_FREE(tmp);
3618 }
3619 else
3620 printf("\n");
3621
3622 return;
3623}
3624
3625int sh_hash_list_db (const char * db_file)
3626{
3627 sh_file_t * p;
3628 SL_TICKET fd;
3629 char * line;
3630
3631 if (!db_file)
3632 {
3633 _exit(EXIT_FAILURE);
3634 return -1;
3635 }
3636 if (sl_is_suid())
3637 {
3638 fprintf(stderr, _("ERROR: insufficient privilege\n"));
3639 _exit (EXIT_FAILURE);
3640 return -1; /* for Mac OSX compiler */
3641 }
3642 if (0 == strcmp(db_file, _("default")))
3643 db_file = file_path('D', 'W');
3644 if (!db_file)
3645 {
3646 _exit(EXIT_FAILURE);
3647 return -1;
3648 }
3649
3650 line = SH_ALLOC(MAX_PATH_STORE+1);
3651
3652 if ( SL_ISERROR(fd = sl_open_read(db_file, SL_YESPRIV)))
3653 {
3654 fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"),
3655 db_file, fd);
3656 _exit(EXIT_FAILURE);
3657 return -1;
3658 }
3659
3660 /* fast forward to start of data
3661 */
3662 sh_hash_setdataent(fd, line, MAX_PATH_STORE, db_file);
3663
3664 while (1)
3665 {
3666 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE);
3667 if ((p != NULL) && (p->fullpath[0] != 'K'))
3668 {
3669 if (ListFullDetail == S_FALSE)
3670 sh_hash_list_db_entry (p);
3671 else
3672 sh_hash_list_db_entry_full_detail (p);
3673 }
3674 else if (p == NULL)
3675 {
3676 break;
3677 }
3678 }
3679
3680 if (line != NULL)
3681 SH_FREE(line);
3682 sl_close (fd);
3683
3684 fflush(NULL);
3685
3686 _exit(EXIT_SUCCESS);
3687 return 0;
3688}
3689
3690/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
3691#endif
Note: See TracBrowser for help on using the repository browser.