source: trunk/src/sh_hash.c@ 328

Last change on this file since 328 was 320, checked in by katerina, 14 years ago

Fix for ticket #237: Potential deadlock in sh_hash_hashdelete()

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