source: trunk/src/sh_hash.c@ 285

Last change on this file since 285 was 279, checked in by katerina, 15 years ago

Fix for tickets #200 to #206 (kernel check, login checks, bugfixes).

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