source: trunk/src/sh_hash.c@ 110

Last change on this file since 110 was 107, checked in by rainer, 17 years ago

Fix incorrect handling of files with zero size in GrowingLogFiles.

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