source: trunk/src/sh_hash.c@ 263

Last change on this file since 263 was 252, checked in by katerina, 15 years ago

Add code to check for stale file records on close() and fclose(), fix sl_close() to handle open stream (ticket #163).

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, sl_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.