source: trunk/src/sh_hash.c@ 448

Last change on this file since 448 was 444, checked in by katerina, 11 years ago

Support for sha2-256 checksum (ticket #348).

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