source: trunk/src/sh_hash.c@ 293

Last change on this file since 293 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
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000, 2001, 2002 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22/* define this if you want version 1.3 style database file */
23/* #define OLD_BUG */
24
25/* make sure state changes of a file are always reported, even
26 * with reportonlyonce=true
27 */
28/* #define REPLACE_OLD *//* moved to samhain.h */
29
30#include <stdlib.h>
31#include <string.h>
32#include <stdio.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <unistd.h>
36
37#ifdef MAJOR_IN_MKDEV
38#include <sys/mkdev.h>
39#else
40#ifdef MAJOR_IN_SYSMACROS
41#include <sys/sysmacros.h>
42#endif
43#endif
44
45#ifdef HAVE_MEMORY_H
46#include <memory.h>
47#endif
48
49#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
50
51#include "sh_hash.h"
52#include "sh_utils.h"
53#include "sh_error.h"
54#include "sh_tiger.h"
55#include "sh_gpg.h"
56#include "sh_unix.h"
57#include "sh_files.h"
58#include "sh_ignore.h"
59#include "sh_pthread.h"
60
61#if defined(SH_WITH_CLIENT)
62#include "sh_forward.h"
63#endif
64
65
66#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
67
68
69#undef FIL__
70#define FIL__ _("sh_hash.c")
71
72SH_MUTEX_STATIC(mutex_hash,PTHREAD_MUTEX_INITIALIZER);
73
74const char notalink[2] = { '-', '\0' };
75
76static char * all_items (file_type * theFile, char * fileHash, int is_new);
77
78#define QUOTE_CHAR '='
79
80char * unquote_string (const char * str, size_t len)
81{
82 int i = 0, t1, t2;
83 char * tmp = NULL;
84 size_t l2, j, k = 0;
85
86 SL_ENTER(_("unquote_string"));
87
88 if (str != NULL)
89 {
90 l2 = len - 2;
91 tmp = SH_ALLOC(len + 1);
92
93 for (j = 0; j <= len; ++j)
94 {
95 if (str[j] != QUOTE_CHAR)
96 {
97 tmp[k] = str[j];
98 }
99 else if (str[j] == QUOTE_CHAR && j < l2)
100 {
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 }
113 }
114 else
115 tmp[k] = str[j];
116 ++k;
117 }
118 }
119 SL_RETURN(tmp, _("unquote_string"));
120}
121
122
123static char * int2hex (unsigned char i, char * i2h)
124{
125 static char hexchars[] = "0123456789ABCDEF";
126
127 i2h[0] = hexchars[(((i) & 0xF0) >> 4)]; /* high */
128 i2h[1] = hexchars[((i) & 0x0F)]; /* low */
129
130 return i2h;
131}
132
133
134char * quote_string (const char * str, size_t len)
135{
136 char * tmp;
137 char * tmp2;
138 size_t l2, j, i = 0, k = 0;
139 char i2h[2];
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
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
164 for (j = 0; j <= len; ++j)
165 {
166 if (str[j] == '\n')
167 {
168 tmp2 = int2hex((unsigned char) '\n', i2h); /* was 'n', fixed in 1.5.4 */
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 {
175 tmp2 = int2hex((unsigned char) QUOTE_CHAR, i2h);
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 {
249
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;
267 char c_attributes[ATTRBUF_SIZE];
268#endif
269#else
270 /* #if defined(__linux__) */
271 UINT32 attributes;
272 char c_attributes[ATTRBUF_SIZE];
273 /* endif */
274#endif
275 unsigned short mark;
276 char c_owner[USER_MAX+2];
277 char c_group[GROUP_MAX+2];
278 char c_mode[CMODE_SIZE];
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;
286 char * attr_string;
287 int fflags;
288 unsigned long modi_mask;
289 struct file_info * next;
290} sh_file_t;
291
292 static const char *policy[] = {
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]"),
302 N_("[User2]"),
303 N_("[User3]"),
304 N_("[User4]"),
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 */
320/* #define TABSIZE 2048 */
321#define TABSIZE 65536
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
337#define REC_FLAGS_ATTR (1<<8)
338#define REC_FLAGS_MASK 0xFF00
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;
355#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
356 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, ATTRBUF_SIZE);
357 theFile->attributes = p->theFile.attributes;
358#endif
359
360 sl_strlcpy(theFile->fullpath, p->fullpath, PATH_MAX);
361 if (p->linkpath != NULL /* && theFile->c_mode[0] == 'l' */)
362 {
363 theFile->link_path = sh_util_strdup(p->linkpath);
364 }
365 else
366 {
367 theFile->link_path = NULL;
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
387 if (p->attr_string)
388 theFile->attr_string = sh_util_strdup(p->attr_string);
389 else
390 theFile->attr_string = NULL;
391
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 **************************************************************/
404
405static int hashfunc(char *s)
406{
407 unsigned int n = 0;
408
409 for ( ; *s; s++)
410 n = 31 * n + *s;
411
412 return n & (TABSIZE - 1); /* % TABSIZE */;
413}
414
415
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;
423 char hashbuf[KEYBUF_SIZE];
424 int retval;
425
426 /* -------- find the entry for the file ---------------- */
427
428 SH_MUTEX_LOCK(mutex_hash);
429
430 retval = 0;
431
432 if (sl_strlen(fullpath) <= MAX_PATH_STORE)
433 p = hashsearch(fullpath);
434 else
435 p = hashsearch( sh_tiger_hash(fullpath,
436 TIGER_DATA,
437 sl_strlen(fullpath),
438 hashbuf, sizeof(hashbuf))
439 );
440 if (p == NULL)
441 {
442 retval = -1;
443 goto unlock_and_return;
444 }
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);
453 if (theFile->attr_string) SH_FREE(theFile->attr_string);
454 if (theFile->link_path) SH_FREE(theFile->link_path);
455 SH_FREE(theFile);
456
457 unlock_and_return:
458 ; /* 'label at end of compound statement */
459 SH_MUTEX_UNLOCK(mutex_hash);
460 return retval;
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
492 /* Not a fully qualified path, i.e. some info stored by some module
493 */
494 if (p->fullpath[0] != '/')
495 {
496 SL_RET0(_("hash_unvisited"));
497 }
498
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
503 *
504 * Files/directories under IgnoreAll are noticed as missing already
505 * during the file check.
506 */
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)))
510 {
511 i = retry_lstat(FIL__, __LINE__, p->fullpath, &buf);
512
513 /* if file does not exist
514 */
515 if (0 != i)
516 {
517 ptr = sh_util_dirname (p->fullpath);
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 }
526
527 /* Only report if !SH_FFLAG_CHECKED_SET
528 */
529 if (!SH_FFLAG_CHECKED_SET(p->fflags))
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);
540 if (theFile->attr_string) SH_FREE(theFile->attr_string);
541 if (theFile->link_path) SH_FREE(theFile->link_path);
542 SH_FREE(theFile);
543
544 SH_FREE(tmp);
545 }
546 }
547
548 /* We rewrite the db on update, thus we need to keep this
549 * if the user does not want to purge it from the db.
550 */
551
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)))
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 {
569 if (p->linkpath != notalink)
570 SH_FREE(p->linkpath);
571 p->linkpath = NULL;
572 }
573 if (p->attr_string)
574 {
575 SH_FREE(p->attr_string);
576 p->attr_string = NULL;
577 }
578 SH_FREE(p);
579 p = NULL;
580 SL_RET0(_("hash_unvisited"));
581#else
582 SET_SH_FFLAG_REPORTED(p->fflags);
583#endif
584 }
585 }
586 }
587
588 else if (SH_FFLAG_VISITED_SET(p->fflags) && SH_FFLAG_REPORTED_SET(p->fflags)
589 && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)))
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);
600 if (theFile->attr_string)
601 SH_FREE(theFile->attr_string);
602 SH_FREE(theFile);
603
604 SH_FREE(tmp);
605 }
606
607 CLEAR_SH_FFLAG_REPORTED(p->fflags);
608 }
609
610 if (sh.flag.reportonce == S_FALSE)
611 CLEAR_SH_FFLAG_REPORTED(p->fflags);
612
613 CLEAR_SH_FFLAG_VISITED(p->fflags);
614 CLEAR_SH_FFLAG_CHECKED(p->fflags);
615
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"));
630
631 SH_MUTEX_LOCK(mutex_hash);
632 for (i = 0; i < TABSIZE; ++i)
633 {
634 if (tab[i] != NULL)
635 hash_unvisited (i, tab[i], tab[i], level);
636 }
637 SH_MUTEX_UNLOCK(mutex_hash);
638
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 {
665 if (p->linkpath != notalink)
666 SH_FREE(p->linkpath);
667 p->linkpath = NULL;
668 }
669 if (p->attr_string)
670 {
671 SH_FREE(p->attr_string);
672 p->attr_string = NULL;
673 }
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
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 }
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;
709 sh_file_t * q;
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 &&
728 0 == strcmp(s->fullpath, p->fullpath))
729 {
730 q = p->next;
731 SH_FREE(p->fullpath);
732 if(p->linkpath && p->linkpath != notalink)
733 SH_FREE(p->linkpath);
734 if(p->attr_string)
735 SH_FREE(p->attr_string);
736 memcpy(p, s, sizeof(sh_file_t));
737 p->next = q;
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) {
769 if (sizeofline > 0) line[0] = '\0';
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);
779 if (n > 0) {
780 --n;
781 line[n] = '\0'; /* remove terminating '\n' */
782 }
783 return n;
784}
785
786static void sh_hash_getline_end (void)
787{
788 sl_fclose (FIL__, __LINE__, sh_fin_fd);
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 ******************************************************************/
807int sh_hash_setdataent (SL_TICKET fd, char * line, int size, const char * file)
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 {
818 sl_fclose (FIL__, __LINE__, sh_fin_fd);
819 sh_fin_fd = NULL;
820 }
821
822 sh_fin_fd = fdopen(dup(get_the_fd(fd)), "rb");
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 {
836 i = sh_hash_getline (sh_fin_fd, line, size);
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;
905 size_t len;
906 char * fullpath;
907 char * linkpath;
908 char * attr_string = NULL;
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));
940#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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
949 if ((ft.mark & ~REC_FLAGS_MASK) != REC_MAGIC)
950 {
951 SH_FREE(p);
952 SL_RETURN( NULL, _("sh_hash_getdataent"));
953 }
954
955 /* Read next record -- Part Two -- Fullpath
956 */
957 i = sh_hash_getline (sh_fin_fd, line, size);
958 if (i <= 0 )
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
972 tmp = unquote_string (line, i);
973 len = sl_strlen(tmp)+1;
974 fullpath = SH_ALLOC(len);
975 (void) sl_strlcpy (fullpath, tmp, len);
976 if (tmp)
977 SH_FREE(tmp);
978 if (fullpath[len-2] == '\n')
979 fullpath[len-2] = '\0';
980
981 /* Read next record -- Part Three -- Linkpath
982 */
983 i = sh_hash_getline (sh_fin_fd, line, size);
984 if (i <= 0 )
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
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 {
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';
1012 }
1013
1014 if (tmp)
1015 SH_FREE(tmp);
1016
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);
1022 if (i <= 0 )
1023 {
1024 SH_FREE(line);
1025 SH_FREE(fullpath);
1026 if (linkpath != notalink)
1027 SH_FREE(linkpath);
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
1039 tmp = unquote_string (line, i);
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
1050 /* Read next record -- Part Four -- Decode
1051 */
1052#if defined(SH_STEALTH)
1053 sh_do_decode(fullpath, sl_strlen(fullpath));
1054
1055#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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
1065 if (ft.c_mode[0] == 'l' && linkpath != notalink)
1066 {
1067 sh_do_decode(linkpath, sl_strlen(linkpath));
1068 }
1069 if ((ft.mark & REC_FLAGS_ATTR) != 0)
1070 {
1071 sh_do_decode(attr_string, sl_strlen(attr_string));
1072 }
1073#endif
1074
1075 memcpy( &(*p).theFile, &ft, sizeof(sh_filestore_t) );
1076
1077 /* init fflags, such that suid files in
1078 * database are recognized as such
1079 */
1080 {
1081 mode_t mode = (mode_t) ft.mode;
1082
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
1099 p->modi_mask = 0L;
1100 p->fullpath = fullpath;
1101 p->linkpath = linkpath;
1102
1103 p->attr_string = attr_string;
1104
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{
1119
1120#define FGETS_BUF 16384
1121
1122 sh_file_t * p;
1123 SL_TICKET fd;
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);
1130 FILE * fin_cp = NULL;
1131
1132 char * buf = NULL;
1133 int bufc;
1134 int flag_pgp;
1135 int flag_nohead;
1136 SL_TICKET fdTmp = (-1);
1137 SL_TICKET open_tmp (void);
1138#endif
1139 char hashbuf[KEYBUF_SIZE];
1140
1141 volatile int retval = 0;
1142 volatile int exitval = EXIT_SUCCESS;
1143
1144 SL_ENTER(_("sh_hash_init"));
1145
1146 SH_MUTEX_LOCK(mutex_hash);
1147
1148#if defined(WITH_GPG) || defined(WITH_PGP)
1149 flag_pgp = S_FALSE;
1150 flag_nohead = S_FALSE;
1151#endif
1152
1153 if (IsInit == 1)
1154 {
1155 goto unlock_and_return;
1156 }
1157
1158 fd = (-1);
1159
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);
1175 retval = 1; exitval = EXIT_FAILURE;
1176 goto unlock_and_return;
1177 }
1178 sl_rewind (fd);
1179
1180 sl_strlcpy (sh.data.hash,
1181 sh_tiger_hash (file_path('C', 'R'),
1182 fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
1183 KEY_LEN+1);
1184 sl_rewind (fd);
1185 }
1186 else
1187#endif
1188 /* Local data file
1189 */
1190
1191 if (fd == (-1))
1192 {
1193 if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__,
1194 file_path('D', 'R'), SL_YESPRIV)))
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);
1203 retval = 1; exitval = EXIT_FAILURE;
1204 goto unlock_and_return;
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,
1211 sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
1212 hashbuf, sizeof(hashbuf)),
1213 KEY_LEN)
1214 && sh.flag.checkSum != SH_CHECK_INIT)
1215 {
1216 dlog(1, FIL__, __LINE__,
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)));
1220 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH,
1221 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1222 file_path('D', 'R') )
1223 );
1224 retval = 1; exitval = EXIT_FAILURE;
1225 goto unlock_and_return;
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;
1235 retval = 1; exitval = EXIT_SUCCESS;
1236 goto unlock_and_return;
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
1246 fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
1247 buf = SH_ALLOC(FGETS_BUF);
1248
1249 while (NULL != fgets(buf, FGETS_BUF, fin_cp))
1250 {
1251 bufc = 0;
1252 while (bufc < FGETS_BUF) {
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;
1261 retval = 1; exitval = EXIT_SUCCESS;
1262 goto unlock_and_return;
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);
1309 sl_fclose(FIL__, __LINE__, fin_cp); /* fin_cp = fdopen(dup(), "rb"); */
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 {
1318 retval = 1; exitval = EXIT_FAILURE;
1319 goto unlock_and_return;
1320 }
1321 sl_rewind (fd);
1322#endif
1323 /* } new 1.4.8 check sig also for files downloaded from server */
1324
1325 line = SH_ALLOC(MAX_PATH_STORE+2);
1326
1327 /* fast forward to start of data
1328 */
1329 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, file_path('D', 'R'));
1330
1331 for (i = 0; i < TABSIZE; ++i)
1332 tab[i] = NULL;
1333
1334 while (1)
1335 {
1336 if (sig_termfast == 1) /* SIGTERM */
1337 {
1338 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1339 --sig_raised; --sig_urgent;
1340 retval = 1; exitval = EXIT_SUCCESS;
1341 SH_FREE(line);
1342 line = NULL;
1343 goto unlock_and_return;
1344 }
1345
1346 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
1347 if (p != NULL)
1348 {
1349 hashinsert (p);
1350 ++count;
1351 }
1352 else
1353 break;
1354 }
1355
1356 /* Initialization completed.
1357 */
1358 IsInit = 1;
1359
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
1369 unlock_and_return:
1370 ; /* 'label at end of compound statement */
1371 SH_MUTEX_UNLOCK(mutex_hash);
1372 if (retval == 0)
1373 {
1374 SL_RET0(_("sh_hash_init"));
1375 }
1376 aud_exit (FIL__, __LINE__, exitval);
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"));
1389 SH_MUTEX_LOCK(mutex_hash);
1390
1391 if (IsInit == 0)
1392 goto unlock_and_exit;
1393
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;
1401
1402 unlock_and_exit:
1403 ; /* 'label at end of compound statement */
1404 SH_MUTEX_UNLOCK(mutex_hash);
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
1420int sh_hash_pushdata_stdout (const char * str)
1421{
1422 if (!str)
1423 { pushdata_stdout = S_TRUE; return 0; }
1424 return -1;
1425}
1426
1427int sh_hash_version_string(const char * str)
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 }
1439 sh_db_version_string = sh_util_strdup(str);
1440 return 0;
1441 }
1442 return -1;
1443}
1444
1445static int sh_loosedircheck = S_FALSE;
1446
1447int sh_hash_loosedircheck(const char * str)
1448{
1449 return sh_util_flagval(str, &sh_loosedircheck);
1450}
1451
1452
1453static void sh_hash_pushdata_int (file_type * buf, char * fileHash)
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;
1462 size_t path_len = 0;
1463
1464 sh_filestore_t p;
1465
1466 struct stat sbuf;
1467
1468 char * fullpath = NULL;
1469 char * linkpath = NULL;
1470 char * attr_string = NULL;
1471
1472 char * line = NULL;
1473
1474 char timestring[81];
1475
1476#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
1477 int i;
1478#endif
1479
1480 SL_ENTER(_("sh_hash_pushdata_int"));
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,
1501 _("sh_hash_pushdata_int"));
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,
1512 _("sh_hash_pushdata_int"));
1513 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1514 }
1515
1516
1517 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) &&
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,
1526 _("sh_hash_pushdata_int"));
1527 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1528 }
1529
1530
1531 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE))
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 {
1549 if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
1550 {
1551 if ( SL_ISERROR(pushdata_fd = sl_open_write(FIL__, __LINE__,
1552 file_path('D', 'W'),
1553 SL_YESPRIV)))
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'));
1559 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1560 }
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
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,
1577 _("Failed to seek to end of baseline database"),
1578 _("sh_hash_pushdata_int"),
1579 file_path('D', 'W'));
1580 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1581 }
1582 }
1583 }
1584 else /* update == TRUE */
1585 {
1586 if (pushdata_isfirst == 1)
1587 {
1588 TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")))
1589 if ( SL_ISERROR(pushdata_fd = sl_open_rdwr(FIL__, __LINE__,
1590 file_path('D', 'W'),
1591 SL_YESPRIV))){
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
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);
1617 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
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
1629 tmp = quote_string(buf->fullpath, old_len);
1630 tmp_len = sl_strlen(tmp);
1631#if defined(SH_STEALTH)
1632 sh_do_decode(buf->fullpath, old_len);
1633#endif
1634
1635 if (tmp && tmp_len <= MAX_PATH_STORE)
1636 {
1637 sl_strlcpy(fullpath, buf->fullpath, MAX_PATH_STORE+1);
1638 }
1639 else
1640 {
1641 char hashbuf[KEYBUF_SIZE];
1642
1643 sl_strlcpy(fullpath,
1644 sh_tiger_hash (buf->fullpath,
1645 TIGER_DATA, old_len,
1646 hashbuf, sizeof(hashbuf)),
1647 KEY_LEN+1);
1648 }
1649 if (tmp) SH_FREE(tmp);
1650 }
1651
1652 path_len = sl_strlen(fullpath);
1653#if defined(SH_STEALTH)
1654 sh_do_encode(fullpath, path_len);
1655#endif
1656
1657 tmp = quote_string(fullpath, path_len);
1658 if (tmp) {
1659 sl_strlcpy(fullpath, tmp, MAX_PATH_STORE+1);
1660 SH_FREE(tmp);
1661 }
1662
1663 if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL)
1664 {
1665
1666 old_len = sl_strlen(buf->link_path);
1667#if defined(SH_STEALTH)
1668 if (buf->c_mode[0] == 'l')
1669 sh_do_encode(buf->link_path, old_len);
1670#endif
1671 tmp = quote_string(buf->link_path, old_len);
1672 tmp_len = sl_strlen(tmp);
1673#if defined(SH_STEALTH)
1674 if (buf->c_mode[0] == 'l')
1675 sh_do_decode(buf->link_path, old_len);
1676#endif
1677
1678 if (tmp && tmp_len <= MAX_PATH_STORE)
1679 {
1680 sl_strlcpy(linkpath, buf->link_path, MAX_PATH_STORE+1);
1681 }
1682 else
1683 {
1684 char hashbuf[KEYBUF_SIZE];
1685 sl_strlcpy(linkpath,
1686 sh_tiger_hash (buf->link_path,
1687 TIGER_DATA, old_len,
1688 hashbuf, sizeof(hashbuf)),
1689 KEY_LEN+1);
1690 }
1691 if (tmp) SH_FREE(tmp);
1692
1693 path_len = sl_strlen(linkpath);
1694#if defined(SH_STEALTH)
1695 if (buf->c_mode[0] == 'l')
1696 sh_do_encode(linkpath, path_len);
1697#endif
1698 tmp = quote_string(linkpath, path_len);
1699 if (tmp)
1700 {
1701 sl_strlcpy(linkpath, tmp, MAX_PATH_STORE+1);
1702 SH_FREE(tmp);
1703 }
1704 }
1705
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
1712 tmp = quote_string(buf->attr_string, old_len);
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
1724 if (buf != NULL) {
1725 p.mark = REC_MAGIC;
1726 if (attr_string)
1727 p.mark |= REC_FLAGS_ATTR;
1728 sl_strlcpy(p.c_mode, buf->c_mode, CMODE_SIZE);
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 }
1734#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1735 sl_strlcpy(p.c_attributes, buf->c_attributes, ATTRBUF_SIZE);
1736#else
1737 for (i = 0; i < ATTRBUF_USED; ++i) p.c_attributes[i] = '-';
1738 p.c_attributes[ATTRBUF_USED] = '\0';
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
1750#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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);
1806 (void) sh_unix_time(0, timestring, sizeof(timestring));
1807 sl_write (pushdata_fd, timestring, strlen(timestring));
1808 sl_write (pushdata_fd, "\n", 1);
1809 } else {
1810 printf ("%s",_("\n#Host "));
1811 printf ("%s", sh.host.name);
1812 printf ("%s",_(" Version "));
1813 printf ("%s", sh_db_version_string);
1814 printf ("%s",_(" Date "));
1815 (void) sh_unix_time(0, timestring, sizeof(timestring));
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));
1844 sl_write_line_fast (pushdata_fd, fullpath, sl_strlen(fullpath));
1845 sl_write_line_fast (pushdata_fd, linkpath, sl_strlen(linkpath));
1846 if (attr_string)
1847 sl_write_line_fast (pushdata_fd, attr_string, sl_strlen(attr_string));
1848 } else {
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 }
1861 }
1862
1863 ++p_count;
1864
1865 if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
1866 {
1867 if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
1868 {
1869 sl_close (pushdata_fd);
1870 pushdata_fd = -1;
1871 }
1872 }
1873
1874 SH_FREE(fullpath);
1875 SH_FREE(linkpath);
1876 if (attr_string)
1877 SH_FREE(attr_string);
1878
1879 SL_RET0(_("sh_hash_pushdata_int"));
1880}
1881
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
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
1909 SH_MUTEX_LOCK(mutex_writeout);
1910 if (!SL_ISERROR(pushdata_fd))
1911 {
1912 sl_close(pushdata_fd);
1913 pushdata_fd = -1;
1914 }
1915 pushdata_isfirst = 1;
1916
1917
1918 SH_MUTEX_LOCK(mutex_hash);
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);
1924 sh_hash_pushdata_int (f, fileHash);
1925 if (f->attr_string) SH_FREE(f->attr_string);
1926 if (f->link_path) SH_FREE(f->link_path);
1927 SH_FREE(f);
1928 }
1929 }
1930 SH_MUTEX_UNLOCK(mutex_hash);
1931
1932 if (!SL_ISERROR(pushdata_fd))
1933 {
1934 sl_close(pushdata_fd);
1935 pushdata_fd = -1;
1936 }
1937 pushdata_isfirst = 1;
1938 SH_MUTEX_UNLOCK(mutex_writeout);
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;
1952 char hashbuf[KEYBUF_SIZE];
1953
1954 SL_ENTER(_("sh_hash_have_it_int"));
1955
1956 if (newname == NULL)
1957 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
1958
1959 if (sl_strlen(newname) <= MAX_PATH_STORE)
1960 p = hashsearch(newname);
1961 else
1962 p = hashsearch ( sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
1963 hashbuf, sizeof(hashbuf)) );
1964 if (p == NULL)
1965 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
1966
1967 SL_RETURN( (p), _("sh_hash_have_it_int"));
1968}
1969
1970int sh_hash_have_it (char * newname)
1971{
1972 sh_file_t * p;
1973 int retval;
1974
1975 if (IsInit != 1)
1976 sh_hash_init();
1977
1978 SH_MUTEX_LOCK(mutex_hash);
1979
1980 retval = 0;
1981
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;
1993}
1994
1995int sh_hash_get_it (char * newname, file_type * tmpFile)
1996{
1997 sh_file_t * p;
1998 int retval;
1999
2000 if (IsInit != 1)
2001 sh_hash_init();
2002
2003 tmpFile->link_path = NULL;
2004 tmpFile->attr_string = NULL;
2005
2006 SH_MUTEX_LOCK(mutex_hash);
2007
2008 retval = (-1);
2009
2010 p = sh_hash_have_it_int (newname);
2011 if (p)
2012 {
2013 sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
2014 if (p->linkpath)
2015 tmpFile->link_path = sh_util_strdup (p->linkpath);
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;
2025}
2026
2027int sh_hash_getflags (char * filename)
2028{
2029 sh_file_t * p;
2030 int retval;
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;
2039 else
2040 retval = -1;
2041 SH_MUTEX_UNLOCK(mutex_hash);
2042 return retval;
2043}
2044
2045int sh_hash_setflags (char * filename, int flags)
2046{
2047 sh_file_t * p;
2048 int retval;
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 }
2060 else
2061 retval = -1;
2062 SH_MUTEX_UNLOCK(mutex_hash);
2063 return retval;
2064}
2065
2066/* needs lock to be threadsafe
2067 */
2068void sh_hash_addflag (char * filename, int flag_to_set)
2069{
2070 sh_file_t * p;
2071
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)
2078 {
2079 p->fflags |= flag_to_set;
2080 }
2081 SH_MUTEX_UNLOCK(mutex_hash);
2082 return;
2083}
2084
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;
2095 char hashbuf[KEYBUF_SIZE];
2096 int retval;
2097
2098 SL_ENTER(_("sh_hash_set_visited_int"));
2099
2100 if (newname == NULL)
2101 SL_RETURN((-1), _("sh_hash_set_visited_int"));
2102
2103 if (IsInit != 1)
2104 sh_hash_init();
2105
2106 SH_MUTEX_LOCK(mutex_hash);
2107
2108 if (sl_strlen(newname) <= MAX_PATH_STORE)
2109 p = hashsearch(newname);
2110 else
2111 p = hashsearch (sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
2112 hashbuf, sizeof(hashbuf)));
2113
2114 if (p)
2115 {
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 }
2122 else
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;
2132 }
2133 else
2134 retval = -1;
2135
2136 SH_MUTEX_UNLOCK(mutex_hash);
2137 SL_RETURN((retval), _("sh_hash_set_visited_int"));
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"));
2147 i = sh_hash_set_visited_int(newname, SH_FFLAG_CHECKED);
2148 SL_RETURN(i, _("sh_hash_set_visited"));
2149}
2150
2151/* mark the file as visited and reported
2152 */
2153int sh_hash_set_visited (char * newname)
2154{
2155 int i;
2156 SL_ENTER(_("sh_hash_set_visited"));
2157 i = sh_hash_set_visited_int(newname, SH_FFLAG_REPORTED);
2158 SL_RETURN(i, _("sh_hash_set_visited"));
2159}
2160
2161/* mark the file as visited and NOT reported
2162 * used to avoid deletion of file from internal database
2163 */
2164int sh_hash_set_visited_true (char * newname)
2165{
2166 int i;
2167 SL_ENTER(_("sh_hash_set_visited_true"));
2168 i = sh_hash_set_visited_int(newname, 0);
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;
2185 char i2h[2];
2186 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
2187
2188 tmpFile->attr_string = NULL;
2189 tmpFile->link_path = NULL;
2190
2191 sl_strlcpy(tmpFile->fullpath, key, PATH_MAX);
2192 tmpFile->size = val1;
2193 tmpFile->mtime = val2;
2194 tmpFile->ctime = val3;
2195
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);
2202
2203 if ((str != NULL) && (size < (PATH_MAX/2)-1))
2204 {
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);
2212 for (i = 0; i < size; ++i)
2213 {
2214 p = sh_util_charhex (str[i],i2h);
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';
2218 }
2219 }
2220 else
2221 {
2222 for (i = 0; i < 10; ++i)
2223 tmpFile->c_mode[i] = '-';
2224 tmpFile->c_mode[10] = '\0';
2225 tmpFile->link_path = sh_util_strdup("-");
2226 }
2227
2228 if (sh.flag.checkSum == SH_CHECK_CHECK &&
2229 sh.flag.update == S_TRUE)
2230 sh_hash_pushdata_memory (tmpFile, SH_KEY_NULL);
2231 else
2232 sh_hash_pushdata (tmpFile, SH_KEY_NULL);
2233
2234 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
2235 SH_FREE(tmpFile);
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;
2248 char * retval = NULL;
2249 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
2250
2251 *size = 0;
2252
2253 if (0 == sh_hash_get_it (key, tmpFile))
2254 {
2255 *val1 = tmpFile->size;
2256 *val2 = tmpFile->mtime;
2257 *val3 = tmpFile->ctime;
2258
2259 if (tmpFile->link_path && tmpFile->link_path[0] != '-')
2260 {
2261 len = strlen(tmpFile->link_path);
2262
2263 p = SH_ALLOC((len/2)+1);
2264 i = sh_util_hextobinary (p, tmpFile->link_path, len);
2265
2266 if (i == 0)
2267 {
2268 *size = (len/2);
2269 p[*size] = '\0';
2270 retval = p;
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 }
2290 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
2291 SH_FREE(tmpFile);
2292 return retval;
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;
2307
2308 size_t len;
2309 char * fullpath;
2310 char * linkpath;
2311 char * attr_string = NULL;
2312 char hashbuf[KEYBUF_SIZE];
2313
2314 SL_ENTER(_("sh_hash_push_int"));
2315
2316 fp = SH_ALLOC(sizeof(sh_file_t));
2317
2318 p.mark = REC_MAGIC;
2319 if (buf->attr_string)
2320 p.mark |= REC_FLAGS_ATTR;
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);
2325#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2326 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
2327#endif
2328
2329#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2330 p.attributes = (UINT32) buf->attributes;
2331#endif
2332 p.linkmode = (UINT32) buf->linkmode;
2333 p.hardlinks = (UINT32) buf->hardlinks;
2334 p.dev = (UINT64) buf->dev;
2335 p.rdev = (UINT64) buf->rdev;
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) );
2346 fp->fflags = 0; /* init fflags */
2347 fp->modi_mask = 0L;
2348
2349 if (buf->attr_string)
2350 attr_string = sh_util_strdup(buf->attr_string);
2351 fp->attr_string = attr_string;
2352
2353 len = sl_strlen(buf->fullpath);
2354 if (len <= MAX_PATH_STORE)
2355 {
2356 fullpath = SH_ALLOC(len+1);
2357 sl_strlcpy(fullpath, buf->fullpath, len+1);
2358 }
2359 else
2360 {
2361 fullpath = SH_ALLOC(KEY_LEN + 1);
2362 sl_strlcpy(fullpath,
2363 sh_tiger_hash (buf->fullpath, TIGER_DATA, len,
2364 hashbuf, sizeof(hashbuf)),
2365 KEY_LEN+1);
2366 }
2367 fp->fullpath = fullpath;
2368
2369 if (buf->link_path)
2370 {
2371 len = sl_strlen(buf->link_path);
2372 if (len <= MAX_PATH_STORE)
2373 {
2374 linkpath = SH_ALLOC(len+1);
2375 sl_strlcpy(linkpath, buf->link_path, len+1);
2376 }
2377 else
2378 {
2379 linkpath = SH_ALLOC(KEY_LEN + 1);
2380 sl_strlcpy(linkpath,
2381 sh_tiger_hash (buf->link_path, TIGER_DATA, len,
2382 hashbuf, sizeof(hashbuf)),
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
2401#ifndef PRIu64
2402#ifdef HAVE_LONG_32
2403#define PRIu64 "llu"
2404#else
2405#define PRIu64 "lu"
2406#endif
2407#endif
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"),
2418 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
2419#else
2420 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2421 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
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
2438 char * tmp = SH_ALLOC(SH_MSG_BUF);
2439 char * msg = SH_ALLOC(SH_MSG_BUF);
2440
2441 tmp[0] = '\0';
2442 msg[0] = '\0';
2443
2444
2445#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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\" ");
2450 sl_snprintf(tmp, SH_MSG_BUF, format,
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
2462 sl_snprintf(tmp, SH_MSG_BUF, format,
2463 theFile->c_mode,
2464 (long) theFile->mode
2465 );
2466#endif
2467 sl_strlcat(msg, tmp, SH_MSG_BUF);
2468
2469 if (is_new)
2470 format = _("hardlinks_new=\"%lu\" ");
2471 else
2472 format = _("hardlinks_old=\"%lu\" ");
2473 sl_snprintf(tmp, SH_MSG_BUF, format,
2474 (unsigned long) theFile->hardlinks);
2475 sl_strlcat(msg, tmp, SH_MSG_BUF);
2476
2477
2478 if (is_new)
2479 format = _("idevice_new=\"%lu\" ");
2480 else
2481 format = _("idevice_old=\"%lu\" ");
2482 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2483 sl_strlcat(msg, tmp, SH_MSG_BUF);
2484
2485
2486 if (is_new)
2487 format = _("inode_new=\"%lu\" ");
2488 else
2489 format = _("inode_old=\"%lu\" ");
2490 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2491 sl_strlcat(msg, tmp, SH_MSG_BUF);
2492
2493 /*
2494 * also report device for prelude
2495 */
2496#if defined(HAVE_LIBPRELUDE)
2497 if (is_new)
2498 format = _("dev_new=\"%lu,%lu\" ");
2499 else
2500 format = _("dev_old=\"%lu,%lu\" ");
2501 sl_snprintf(tmp, SH_MSG_BUF, format,
2502 (unsigned long) major(theFile->dev),
2503 (unsigned long) minor(theFile->dev));
2504 sl_strlcat(msg, tmp, SH_MSG_BUF);
2505#endif
2506
2507
2508 if (is_new)
2509 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
2510 else
2511 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
2512 sl_snprintf(tmp, SH_MSG_BUF, format,
2513 theFile->c_owner, (long) theFile->owner);
2514 sl_strlcat(msg, tmp, SH_MSG_BUF);
2515
2516
2517 if (is_new)
2518 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
2519 else
2520 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
2521 sl_snprintf(tmp, SH_MSG_BUF, format,
2522 theFile->c_group, (long) theFile->group);
2523 sl_strlcat(msg, tmp, SH_MSG_BUF);
2524
2525
2526 if (is_new)
2527 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2528 (UINT64) 0, (UINT64) theFile->size);
2529 else
2530 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2531 (UINT64) theFile->size, (UINT64) 0);
2532 sl_strlcat(msg, tmp, SH_MSG_BUF);
2533
2534
2535 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2536 if (is_new)
2537 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=\"%s\" "), timstr1c);
2538 else
2539 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" "), timstr1c);
2540 sl_strlcat(msg, tmp, SH_MSG_BUF);
2541
2542 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2543 if (is_new)
2544 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=\"%s\" "), timstr1a);
2545 else
2546 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" "), timstr1a);
2547 sl_strlcat(msg, tmp, SH_MSG_BUF);
2548
2549 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2550 if (is_new)
2551 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=\"%s\" "), timstr1m);
2552 else
2553 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" "), timstr1m);
2554 sl_strlcat(msg, tmp, SH_MSG_BUF);
2555
2556 if (is_new)
2557 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=\"%s\" "), fileHash);
2558 else
2559 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=\"%s\" "), fileHash);
2560 sl_strlcat(msg, tmp, SH_MSG_BUF);
2561
2562 if (theFile->c_mode[0] == 'l' ||
2563 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
2564 {
2565 tmp_lnk = sh_util_safe_name(theFile->link_path);
2566 if (tmp_lnk)
2567 {
2568 if (is_new)
2569 sl_snprintf(tmp, SH_MSG_BUF, _("link_new=\"%s\" "), tmp_lnk);
2570 else
2571 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" "), tmp_lnk);
2572 SH_FREE(tmp_lnk);
2573 sl_strlcat(msg, tmp, SH_MSG_BUF);
2574 }
2575 }
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)
2583 sl_snprintf(tmp, SH_MSG_BUF, _("acl_new=\"%s\" "), tmp_lnk);
2584 else
2585 sl_snprintf(tmp, SH_MSG_BUF, _("acl_old=\"%s\" "), tmp_lnk);
2586 SH_FREE(tmp_lnk);
2587 sl_strlcat(msg, tmp, SH_MSG_BUF);
2588 }
2589 }
2590
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
2605 char * tmp = SH_ALLOC(SH_MSG_BUF);
2606 char * msg = SH_ALLOC(SH_MSG_BUF);
2607
2608 tmp[0] = '\0';
2609 msg[0] = '\0';
2610
2611
2612#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
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>, ");
2617 sl_snprintf(tmp, SH_MSG_BUF, format,
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
2629 sl_snprintf(tmp, SH_MSG_BUF, format,
2630 theFile->c_mode,
2631 (long) theFile->mode
2632 );
2633#endif
2634 sl_strlcat(msg, tmp, SH_MSG_BUF);
2635
2636 if (is_new)
2637 format = _("hardlinks_new=<%lu>, ");
2638 else
2639 format = _("hardlinks_old=<%lu>, ");
2640 sl_snprintf(tmp, SH_MSG_BUF, format,
2641 (unsigned long) theFile->hardlinks);
2642 sl_strlcat(msg, tmp, SH_MSG_BUF);
2643
2644
2645 if (is_new)
2646 format = _("idevice_new=<%lu>, ");
2647 else
2648 format = _("idevice_old=<%lu>, ");
2649 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2650 sl_strlcat(msg, tmp, SH_MSG_BUF);
2651
2652
2653 if (is_new)
2654 format = _("inode_new=<%lu>, ");
2655 else
2656 format = _("inode_old=<%lu>, ");
2657 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2658 sl_strlcat(msg, tmp, SH_MSG_BUF);
2659
2660
2661 /*
2662 * also report device for prelude
2663 */
2664#if defined(HAVE_LIBPRELUDE)
2665 if (is_new)
2666 format = _("dev_new=<%lu,%lu>, ");
2667 else
2668 format = _("dev_old=<%lu,%lu>, ");
2669 sl_snprintf(tmp, SH_MSG_BUF, format,
2670 (unsigned long) major(theFile->dev),
2671 (unsigned long) minor(theFile->dev));
2672 sl_strlcat(msg, tmp, SH_MSG_BUF);
2673#endif
2674
2675 if (is_new)
2676 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
2677 else
2678 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
2679 sl_snprintf(tmp, SH_MSG_BUF, format,
2680 theFile->c_owner, (long) theFile->owner);
2681 sl_strlcat(msg, tmp, SH_MSG_BUF);
2682
2683
2684 if (is_new)
2685 format = _("group_new=<%s>, igroup_new=<%ld>, ");
2686 else
2687 format = _("group_old=<%s>, igroup_old=<%ld>, ");
2688 sl_snprintf(tmp, SH_MSG_BUF, format,
2689 theFile->c_group, (long) theFile->group);
2690 sl_strlcat(msg, tmp, SH_MSG_BUF);
2691
2692
2693 if (is_new)
2694 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2695 (UINT64) 0, (UINT64) theFile->size);
2696 else
2697 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2698 (UINT64) theFile->size, (UINT64) 0);
2699 sl_strlcat(msg, tmp, SH_MSG_BUF);
2700
2701
2702 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2703 if (is_new)
2704 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=<%s>, "), timstr1c);
2705 else
2706 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, "), timstr1c);
2707 sl_strlcat(msg, tmp, SH_MSG_BUF);
2708
2709 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2710 if (is_new)
2711 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=<%s>, "), timstr1a);
2712 else
2713 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, "), timstr1a);
2714 sl_strlcat(msg, tmp, SH_MSG_BUF);
2715
2716 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2717 if (is_new)
2718 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=<%s>, "), timstr1m);
2719 else
2720 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, "), timstr1m);
2721 sl_strlcat(msg, tmp, SH_MSG_BUF);
2722
2723 if (is_new)
2724 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=<%s>"), fileHash);
2725 else
2726 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=<%s>"), fileHash);
2727 sl_strlcat(msg, tmp, SH_MSG_BUF);
2728
2729 if (theFile->c_mode[0] == 'l' ||
2730 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
2731 {
2732 tmp_lnk = sh_util_safe_name(theFile->link_path);
2733 if (tmp_lnk)
2734 {
2735 if (is_new)
2736 sl_snprintf(tmp, SH_MSG_BUF, _(", link_new=<%s> "), tmp_lnk);
2737 else
2738 sl_snprintf(tmp, SH_MSG_BUF, _(", link_old=<%s> "), tmp_lnk);
2739 SH_FREE(tmp_lnk);
2740 sl_strlcat(msg, tmp, SH_MSG_BUF);
2741 }
2742 }
2743
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)
2750 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_new=<%s> "), tmp_lnk);
2751 else
2752 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_old=<%s> "), tmp_lnk);
2753 SH_FREE(tmp_lnk);
2754 sl_strlcat(msg, tmp, SH_MSG_BUF);
2755 }
2756 }
2757
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 {
2772 SH_MUTEX_LOCK(mutex_hash);
2773 hashinsert (p);
2774 p->modi_mask = theFile->check_mask;
2775 SH_MUTEX_UNLOCK(mutex_hash);
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];
2806 char * linkComp;
2807 int maxcomp;
2808
2809 char change_code[16];
2810 int i;
2811
2812 unsigned long modi_mask;
2813
2814 char log_policy[32];
2815 volatile int log_severity;
2816 char hashbuf[KEYBUF_SIZE];
2817
2818 int retval;
2819
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
2834 SH_MUTEX_LOCK(mutex_hash);
2835
2836 modi_mask = 0;
2837 retval = 0;
2838
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,
2844 sl_strlen(theFile->fullpath),
2845 hashbuf, sizeof(hashbuf))
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)
2868 SET_SH_FFLAG_REPORTED(theFile->file_reported);
2869
2870 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2871 {
2872 p = sh_hash_push_int(theFile, fileHash);
2873 if (p)
2874 {
2875 hashinsert (p);
2876 p->modi_mask = theFile->check_mask;
2877 }
2878 }
2879
2880 else if (S_TRUE == sh.flag.update)
2881 {
2882 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
2883 {
2884 p = sh_hash_push_int(theFile, fileHash);
2885 if (p)
2886 {
2887 hashinsert (p);
2888 p->modi_mask = theFile->check_mask;
2889 }
2890 }
2891 else
2892 {
2893 retval = 1;
2894 goto unlock_and_return;
2895 }
2896 }
2897
2898 goto unlock_and_return;
2899 }
2900
2901 p->modi_mask = theFile->check_mask;
2902
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) &&
2912 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
2913 (theFile->check_mask & MODI_CHK) != 0)
2914 {
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 }
2936 }
2937
2938 if (p->theFile.c_mode[0] == 'l')
2939 {
2940 if (!(theFile->link_path) &&
2941 (theFile->check_mask & MODI_LNK) != 0)
2942 {
2943 linkComp = NULL;
2944 modi_mask |= MODI_LNK;
2945 change_code[1] = 'L';
2946 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
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 }
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)
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
3018#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3019 || (theFile->attributes != p->theFile.attributes)
3020#endif
3021 )
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
3065 if ( (theFile->check_mask & MODI_ATM) != 0 &&
3066 theFile->atime != (time_t) p->theFile.atime)
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 {
3088 if ((theFile->check_mask & MODI_SGROW) == 0 ||
3089 theFile->size < (off_t) p->theFile.size)
3090 {
3091 modi_mask |= MODI_SIZ;
3092 change_code[9] = 'S';
3093 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
3094 }
3095 }
3096 change_code[10] = '\0';
3097
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
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 */
3119 if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
3120 {
3121 tmp = SH_ALLOC(SH_MSG_BUF);
3122 msg = SH_ALLOC(SH_MSG_BUF);
3123 msg[0] = '\0';
3124
3125 if ( ((modi_mask & MODI_MOD) != 0)
3126#if defined(HAVE_LIBPRELUDE)
3127 || ((modi_mask & MODI_USR) != 0)
3128 || ((modi_mask & MODI_GRP) != 0)
3129#endif
3130 )
3131 {
3132#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3133 sl_snprintf(tmp, SH_MSG_BUF,
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
3149 sl_snprintf(tmp, SH_MSG_BUF,
3150 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
3151 p->theFile.c_mode, theFile->c_mode,
3152 (long) p->theFile.mode, (long) theFile->mode);
3153#else
3154 sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=<%s>, mode_new=<%s>, "),
3155 p->theFile.c_mode, theFile->c_mode);
3156#endif
3157#endif
3158 sl_strlcat(msg, tmp, SH_MSG_BUF);
3159
3160#if defined(USE_ACL) || defined(USE_XATTR)
3161 if (theFile->attr_string != NULL || p->attr_string != NULL)
3162 {
3163 sl_snprintf(tmp, SH_MSG_BUF,
3164#ifdef SH_USE_XML
3165 _("acl_old=\"%s\" acl_new=\"%s\" "),
3166#else
3167 _("acl_old=<%s>, acl_new=<%s>, "),
3168#endif
3169 (p->attr_string) ? p->attr_string : _("none"),
3170 (theFile->attr_string) ? theFile->attr_string : _("none"));
3171
3172 sl_strlcat(msg, tmp, SH_MSG_BUF);
3173 }
3174#endif
3175
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;
3187#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3188 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
3189 p->theFile.attributes = theFile->attributes;
3190#endif
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
3205 }
3206 }
3207#endif
3208 }
3209
3210 if ((modi_mask & MODI_HLN) != 0)
3211 {
3212 sl_snprintf(tmp, SH_MSG_BUF,
3213#ifdef SH_USE_XML
3214 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
3215#else
3216 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
3217#endif
3218 (unsigned long) p->theFile.hardlinks,
3219 (unsigned long) theFile->hardlinks);
3220 sl_strlcat(msg, tmp, SH_MSG_BUF);
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 {
3229 sl_snprintf(tmp, SH_MSG_BUF,
3230#ifdef SH_USE_XML
3231 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
3232#else
3233 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
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 );
3244 sl_strlcat(msg, tmp, SH_MSG_BUF);
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 {
3253 sl_snprintf(tmp, SH_MSG_BUF,
3254#ifdef SH_USE_XML
3255 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
3256#else
3257 _("inode_old=<%lu>, inode_new=<%lu>, "),
3258#endif
3259 (unsigned long) p->theFile.ino,
3260 (unsigned long) theFile->ino);
3261 sl_strlcat(msg, tmp, SH_MSG_BUF);
3262#ifdef REPLACE_OLD
3263 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3264 {
3265 p->theFile.ino = theFile->ino;
3266 p->theFile.dev = theFile->dev;
3267 }
3268#endif
3269 }
3270
3271
3272 /*
3273 * also report device for prelude
3274 */
3275#if defined(HAVE_LIBPRELUDE)
3276 if ((modi_mask & MODI_INO) != 0)
3277 {
3278 sl_snprintf(tmp, SH_MSG_BUF,
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 );
3289 sl_strlcat(msg, tmp, SH_MSG_BUF);
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
3297 if ( ((modi_mask & MODI_USR) != 0)
3298#if defined(HAVE_LIBPRELUDE)
3299 || ((modi_mask & MODI_MOD) != 0)
3300#endif
3301 )
3302 {
3303#ifdef SH_USE_XML
3304 sl_snprintf(tmp, SH_MSG_BUF,
3305 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
3306#else
3307 sl_snprintf(tmp, SH_MSG_BUF,
3308 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
3309#endif
3310 p->theFile.c_owner, theFile->c_owner,
3311 (long) p->theFile.owner, (long) theFile->owner
3312 );
3313 sl_strlcat(msg, tmp, SH_MSG_BUF);
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)
3326#if defined(HAVE_LIBPRELUDE)
3327 || ((modi_mask & MODI_MOD) != 0)
3328#endif
3329 )
3330 {
3331#ifdef SH_USE_XML
3332 sl_snprintf(tmp, SH_MSG_BUF,
3333 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
3334 p->theFile.c_group, theFile->c_group,
3335 (long) p->theFile.group, (long) theFile->group);
3336#else
3337 sl_snprintf(tmp, SH_MSG_BUF,
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);
3341#endif
3342
3343 sl_strlcat(msg, tmp, SH_MSG_BUF);
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 {
3357 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
3358 (UINT64) p->theFile.size,
3359 (UINT64) theFile->size);
3360 sl_strlcat(msg, tmp, SH_MSG_BUF);
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 {
3369 (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c));
3370 (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c));
3371#ifdef SH_USE_XML
3372 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
3373 timstr1c, timstr2c);
3374#else
3375 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, ctime_new=<%s>, "),
3376 timstr1c, timstr2c);
3377#endif
3378 sl_strlcat(msg, tmp, SH_MSG_BUF);
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 {
3387 (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a));
3388 (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a));
3389#ifdef SH_USE_XML
3390 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" atime_new=\"%s\" "),
3391 timstr1a, timstr2a);
3392#else
3393 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, atime_new=<%s>, "),
3394 timstr1a, timstr2a);
3395#endif
3396 sl_strlcat(msg, tmp, SH_MSG_BUF);
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 {
3405 (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m));
3406 (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m));
3407#ifdef SH_USE_XML
3408 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
3409 timstr1m, timstr2m);
3410#else
3411 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, mtime_new=<%s>, "),
3412 timstr1m, timstr2m);
3413#endif
3414 sl_strlcat(msg, tmp, SH_MSG_BUF);
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 {
3424 sl_snprintf(tmp, SH_MSG_BUF,
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);
3431 sl_strlcat(msg, tmp, SH_MSG_BUF);
3432#ifdef REPLACE_OLD
3433 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
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 }
3439#endif
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;
3444 }
3445
3446
3447 if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */)
3448 {
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("-");
3457#ifdef SH_USE_XML
3458 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" link_new=\"%s\" "),
3459 tmp_lnk_old, tmp_lnk);
3460#else
3461 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=<%s>, link_new=<%s>"),
3462 tmp_lnk_old, tmp_lnk);
3463#endif
3464 SH_FREE(tmp_lnk);
3465 SH_FREE(tmp_lnk_old);
3466 sl_strlcat(msg, tmp, SH_MSG_BUF);
3467#ifdef REPLACE_OLD
3468 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3469 {
3470 if (p->linkpath != NULL && p->linkpath != notalink)
3471 SH_FREE(p->linkpath);
3472 if (!(theFile->link_path) ||
3473 (theFile->link_path[0] == '-' && theFile->link_path[1] == '\0'))
3474 p->linkpath = (char *)notalink;
3475 else
3476 p->linkpath = sh_util_strdup(theFile->link_path);
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
3493 SET_SH_FFLAG_REPORTED(p->fflags);
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;
3505#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3506 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
3507 theFile->attributes = p->theFile.attributes;
3508#endif
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
3523
3524 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
3525 {
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("-");
3532 }
3533 else
3534 {
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;
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
3561 SET_SH_FFLAG_VISITED(p->fflags);
3562 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3563 retval = 1;
3564 goto unlock_and_return;
3565 }
3566 else /* if (sh.flag.reportonce == S_TRUE) */
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;
3574#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3575 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
3576 p->theFile.attributes = theFile->attributes;
3577#endif
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
3592
3593 if (theFile->c_mode[0] == 'l' || theFile->link_path)
3594 {
3595 if (p->linkpath != NULL && p->linkpath != notalink)
3596 SH_FREE(p->linkpath);
3597 p->linkpath = sh_util_strdup(theFile->link_path);
3598 }
3599 else
3600 {
3601 if (p->linkpath != NULL && p->linkpath != notalink) {
3602 SH_FREE(p->linkpath);
3603 }
3604 p->linkpath = (char *)notalink;
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
3628 SET_SH_FFLAG_VISITED(p->fflags);
3629 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3630
3631 unlock_and_return:
3632 ; /* 'label at end of compound statement */
3633 SH_MUTEX_UNLOCK(mutex_hash);
3634 SL_RETURN(retval, _("sh_hash_compdata"));
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
3647 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
3648 for (i = 0; i < TABSIZE; ++i)
3649 {
3650 for (p = tab[i]; p; p = p->next)
3651 CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
3652 }
3653 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
3654 SL_RETURN (0, _("sh_hash_compdata"));
3655}
3656
3657
3658int hash_remove_tree (char * s)
3659{
3660 sh_file_t * p;
3661 size_t len;
3662 unsigned int i;
3663
3664 SL_ENTER(_("hash_remove_tree"));
3665
3666 if (!s || *s == '\0')
3667 SL_RETURN ((-1), _("hash_remove_tree"));
3668
3669 len = sl_strlen(s);
3670
3671 if (IsInit != 1)
3672 sh_hash_init();
3673
3674 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
3675 for (i = 0; i < TABSIZE; ++i)
3676 {
3677 for (p = tab[i]; p; p = p->next)
3678 {
3679 if (p->fullpath && 0 == strncmp(s, p->fullpath, len))
3680 {
3681 SET_SH_FFLAG_ALLIGNORE(p->fflags);
3682 }
3683 }
3684 }
3685 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
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
3700static int ListFullDetail = S_FALSE;
3701static int ListWithDelimiter = S_FALSE;
3702static char * ListFile = NULL;
3703
3704int set_list_file (const char * c)
3705{
3706 ListFile = sh_util_strdup(c);
3707 return 0;
3708}
3709
3710int set_full_detail (const char * c)
3711{
3712 (void) c;
3713 ListFullDetail = S_TRUE;
3714 return 0;
3715}
3716
3717int set_list_delimited (const char * c)
3718{
3719 (void) c;
3720 ListFullDetail = S_TRUE;
3721 ListWithDelimiter = S_TRUE;
3722 return 0;
3723}
3724
3725/* Always quote the string, except if it is empty. Quote quotes by
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
3802
3803void sh_hash_list_db_entry_full_detail (sh_file_t * p)
3804{
3805 char * tmp;
3806 char * esc;
3807 char str[81];
3808
3809 if (ListWithDelimiter == S_TRUE)
3810 {
3811 printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "),
3812 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
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 {
3821 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
3822 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
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])
3831 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev);
3832 else
3833 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size);
3834
3835 printf( _(" %8s"), str);
3836 if (ListWithDelimiter == S_TRUE)
3837 putchar(',');
3838
3839 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str)));
3840 if (ListWithDelimiter == S_TRUE)
3841 putchar(',');
3842 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str)));
3843 if (ListWithDelimiter == S_TRUE)
3844 putchar(',');
3845 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str)));
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);
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 }
3864 SH_FREE(tmp);
3865
3866 if ('l' == p->theFile.c_mode[0])
3867 {
3868 tmp = sh_util_safe_name(p->linkpath);
3869 if (ListWithDelimiter != S_TRUE)
3870 {
3871 printf(_(" -> %s"), tmp);
3872 }
3873 else
3874 {
3875 esc = csv_escape(tmp);
3876 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3877 if (esc)
3878 SH_FREE(esc);
3879 }
3880 SH_FREE(tmp);
3881 }
3882
3883 if (p->attr_string)
3884 {
3885 tmp = sh_util_safe_name(p->attr_string);
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 }
3897 SH_FREE(tmp);
3898 }
3899 else
3900 {
3901 if (ListWithDelimiter == S_TRUE)
3902 printf("%s",_(" no_attr"));
3903 }
3904 putchar('\n');
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
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
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));
3935#endif
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
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));
3985
3986 clen = dlen * 2 + 1;
3987
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)
3995 { fprintf(stderr, "%s",_("Error: Not enough memory\n")); return -1; }
3996 if (res == Z_DATA_ERROR)
3997 { fprintf(stderr, "%s",_("Error: Data corrupt or incomplete\n")); return -1; }
3998 } while (res == Z_BUF_ERROR || clen == clen_o);
3999
4000 decompressed[clen] = '\0';
4001 fputs( (char*) decompressed, stdout);
4002 SH_FREE(decompressed);
4003 return 0;
4004 }
4005#else
4006 (void) linkpath;
4007#endif
4008 fprintf(stderr, "%s",_("Error: No data available\n"));
4009 return -1;
4010}
4011
4012int sh_hash_list_db (const char * db_file)
4013{
4014 sh_file_t * p;
4015 SL_TICKET fd;
4016 char * line;
4017 int flag = 0;
4018
4019 if (!db_file)
4020 {
4021 _exit(EXIT_FAILURE);
4022 return -1;
4023 }
4024 if (sl_is_suid())
4025 {
4026 fprintf(stderr, "%s",_("ERROR: insufficient privilege\n"));
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
4038 line = SH_ALLOC(MAX_PATH_STORE+2);
4039
4040 if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, db_file, SL_YESPRIV)))
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 */
4050 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, db_file);
4051
4052 while (1)
4053 {
4054 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
4055 if ((p != NULL) && (p->fullpath[0] == '/'))
4056 {
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 }
4065 else
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 {
4082 fprintf(stderr, "%s",_("File is a link\n"));
4083 _exit(EXIT_FAILURE);
4084 return -1;
4085 }
4086 break;
4087 }
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
4101 if (flag == 0)
4102 {
4103 fprintf(stderr, "%s",_("File not found\n"));
4104 _exit(EXIT_FAILURE);
4105 }
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.