source: trunk/src/sh_hash.c@ 457

Last change on this file since 457 was 457, checked in by katerina, 10 years ago

Fix for ticket #357 (Incorrect precedence for IgnoreAll).

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