source: trunk/src/sh_hash.c@ 238

Last change on this file since 238 was 227, checked in by katerina, 16 years ago

Fix warnings with -fstack-check

File size: 99.6 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 fclose (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 fclose (sh_fin_fd);
819 sh_fin_fd = NULL;
820 }
821
822 sh_fin_fd = fdopen(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;
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(file_path('D', 'R'), SL_YESPRIV)))
1194 {
1195 TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s>\n"),
1196 file_path('D', 'R')));
1197 dlog(1, FIL__, __LINE__,
1198 _("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"),
1199 sl_get_errmsg(), fd, (int) sl_ret_euid());
1200 sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1,
1201 sh.prg_name);
1202 retval = 1; exitval = EXIT_FAILURE;
1203 goto unlock_and_return;
1204 }
1205
1206 TPT(( 0, FIL__, __LINE__, _("msg=<Opened database: %s>\n"),
1207 file_path('D', 'R')));
1208
1209 if (0 != sl_strncmp(sh.data.hash,
1210 sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
1211 hashbuf, sizeof(hashbuf)),
1212 KEY_LEN)
1213 && sh.flag.checkSum != SH_CHECK_INIT)
1214 {
1215 dlog(1, FIL__, __LINE__,
1216 _("The checksum of the file signature database has changed since startup: %s -> %s\n"),
1217 sh.data.hash, sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
1218 hashbuf, sizeof(hashbuf)));
1219 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH,
1220 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1221 file_path('D', 'R') )
1222 );
1223 retval = 1; exitval = EXIT_FAILURE;
1224 goto unlock_and_return;
1225 }
1226 sl_rewind (fd);
1227
1228 } /* new 1.4.8 */
1229
1230 if (sig_termfast == 1) /* SIGTERM */
1231 {
1232 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1233 --sig_raised; --sig_urgent;
1234 retval = 1; exitval = EXIT_SUCCESS;
1235 goto unlock_and_return;
1236 }
1237
1238#if defined(WITH_GPG) || defined(WITH_PGP)
1239 /* new 1.4.8: also checked for server data */
1240
1241 /* extract the data and copy to temporary file
1242 */
1243 fdTmp = open_tmp();
1244
1245 fin_cp = fdopen(get_the_fd(fd), "rb");
1246 buf = SH_ALLOC(FGETS_BUF);
1247
1248 while (NULL != fgets(buf, FGETS_BUF, fin_cp))
1249 {
1250 bufc = 0;
1251 while (bufc < FGETS_BUF) {
1252 if (buf[bufc] == '\n') { ++bufc; break; }
1253 ++bufc;
1254 }
1255
1256 if (sig_termfast == 1) /* SIGTERM */
1257 {
1258 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1259 --sig_raised; --sig_urgent;
1260 retval = 1; exitval = EXIT_SUCCESS;
1261 goto unlock_and_return;
1262 }
1263
1264 if (flag_pgp == S_FALSE &&
1265 (0 == sl_strcmp(buf, _("-----BEGIN PGP SIGNED MESSAGE-----\n"))||
1266 0 == sl_strcmp(buf, _("-----BEGIN PGP MESSAGE-----\n")))
1267 )
1268 {
1269 flag_pgp = S_TRUE;
1270 sl_write(fdTmp, buf, bufc);
1271 continue;
1272 }
1273
1274 if (flag_pgp == S_TRUE && flag_nohead == S_FALSE)
1275 {
1276 if (buf[0] == '\n')
1277 {
1278 flag_nohead = S_TRUE;
1279 sl_write(fdTmp, buf, 1);
1280 continue;
1281 }
1282 else if (0 == sl_strncmp(buf, _("Hash:"), 5) ||
1283 0 == sl_strncmp(buf, _("NotDashEscaped:"), 15))
1284 {
1285 sl_write(fdTmp, buf, bufc);
1286 continue;
1287 }
1288 else
1289 continue;
1290 }
1291
1292 if (flag_pgp == S_TRUE && buf[0] == '\n')
1293 {
1294 sl_write(fdTmp, buf, 1);
1295 }
1296 else if (flag_pgp == S_TRUE)
1297 {
1298 /* sl_write_line(fdTmp, buf, bufc); */
1299 sl_write(fdTmp, buf, bufc);
1300 }
1301
1302 if (flag_pgp == S_TRUE &&
1303 0 == sl_strcmp(buf, _("-----END PGP SIGNATURE-----\n")))
1304 break;
1305 }
1306 SH_FREE(buf);
1307 sl_close(fd);
1308 fclose(fin_cp);
1309
1310 fd = fdTmp;
1311 sl_rewind (fd);
1312
1313 /* Validate signature of open file.
1314 */
1315 if (0 != sh_gpg_check_sign (0, fd, 2))
1316 {
1317 retval = 1; exitval = EXIT_FAILURE;
1318 goto unlock_and_return;
1319 }
1320 sl_rewind (fd);
1321#endif
1322 /* } new 1.4.8 check sig also for files downloaded from server */
1323
1324 line = SH_ALLOC(MAX_PATH_STORE+2);
1325
1326 /* fast forward to start of data
1327 */
1328 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, file_path('D', 'R'));
1329
1330 for (i = 0; i < TABSIZE; ++i)
1331 tab[i] = NULL;
1332
1333 while (1)
1334 {
1335 if (sig_termfast == 1) /* SIGTERM */
1336 {
1337 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1338 --sig_raised; --sig_urgent;
1339 retval = 1; exitval = EXIT_SUCCESS;
1340 SH_FREE(line);
1341 line = NULL;
1342 goto unlock_and_return;
1343 }
1344
1345 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
1346 if (p != NULL)
1347 {
1348 hashinsert (p);
1349 ++count;
1350 }
1351 else
1352 break;
1353 }
1354
1355 /* Initialization completed.
1356 */
1357 IsInit = 1;
1358
1359 if (line != NULL)
1360 SH_FREE(line);
1361
1362 /* Always keep db in memory, so we have no open file
1363 */
1364 sl_close (fd);
1365 sh_hash_getline_end();
1366 fd = -1;
1367
1368 unlock_and_return:
1369 ; /* 'label at end of compound statement */
1370 SH_MUTEX_UNLOCK(mutex_hash);
1371 if (retval == 0)
1372 {
1373 SL_RET0(_("sh_hash_init"));
1374 }
1375 aud_exit (FIL__, __LINE__, exitval);
1376}
1377
1378/*****************************************************************
1379 *
1380 * delete hash array
1381 *
1382 *****************************************************************/
1383void sh_hash_hashdelete ()
1384{
1385 int i;
1386
1387 SL_ENTER(_("sh_hash_hashdelete"));
1388 SH_MUTEX_LOCK(mutex_hash);
1389
1390 if (IsInit == 0)
1391 goto unlock_and_exit;
1392
1393 for (i = 0; i < TABSIZE; ++i)
1394 if (tab[i] != NULL)
1395 {
1396 hash_kill (tab[i]);
1397 tab[i] = NULL;
1398 }
1399 IsInit = 0;
1400
1401 unlock_and_exit:
1402 ; /* 'label at end of compound statement */
1403 SH_MUTEX_UNLOCK(mutex_hash);
1404 SL_RET0(_("sh_hash_hashdelete"));
1405}
1406
1407/******************************************************************
1408 *
1409 * Insert a file into the database.
1410 *
1411 ******************************************************************/
1412static int pushdata_isfirst = 1;
1413static SL_TICKET pushdata_fd = -1;
1414
1415static int pushdata_stdout = S_FALSE;
1416
1417static char * sh_db_version_string = NULL;
1418
1419int sh_hash_pushdata_stdout (const char * str)
1420{
1421 if (!str)
1422 { pushdata_stdout = S_TRUE; return 0; }
1423 return -1;
1424}
1425
1426int sh_hash_version_string(const char * str)
1427{
1428 if (str)
1429 {
1430 if (sh_db_version_string != NULL) {
1431 SH_FREE(sh_db_version_string);
1432 }
1433 if (0 == sl_strncmp(str, _("NULL"), 4))
1434 {
1435 sh_db_version_string = NULL;
1436 return 0;
1437 }
1438 sh_db_version_string = sh_util_strdup(str);
1439 return 0;
1440 }
1441 return -1;
1442}
1443
1444static int sh_loosedircheck = S_FALSE;
1445
1446int sh_hash_loosedircheck(const char * str)
1447{
1448 return sh_util_flagval(str, &sh_loosedircheck);
1449}
1450
1451
1452static void sh_hash_pushdata_int (file_type * buf, char * fileHash)
1453{
1454 static long p_count = 0;
1455
1456 int status = 0;
1457
1458 char * tmp;
1459 size_t tmp_len = 0;
1460 size_t old_len = 0;
1461 size_t path_len = 0;
1462
1463 sh_filestore_t p;
1464
1465 struct stat sbuf;
1466
1467 char * fullpath = NULL;
1468 char * linkpath = NULL;
1469 char * attr_string = NULL;
1470
1471 char * line = NULL;
1472
1473 char timestring[81];
1474
1475#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
1476 int i;
1477#endif
1478
1479 SL_ENTER(_("sh_hash_pushdata_int"));
1480
1481 fullpath = SH_ALLOC(MAX_PATH_STORE+1);
1482 linkpath = SH_ALLOC(MAX_PATH_STORE+1);
1483
1484 linkpath[0] = '-';
1485 linkpath[1] = '\0';
1486 fullpath[0] = '-';
1487 fullpath[1] = '\0';
1488
1489 if (!buf) {
1490 memset(&p, '\0', sizeof(sh_filestore_t));
1491 }
1492
1493 if ((pushdata_stdout == S_TRUE) && (sh.flag.update == S_TRUE))
1494 {
1495 dlog(1, FIL__, __LINE__,
1496 _("You cannot write the database to stdout when you use update rather than init.\n"));
1497 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1498 _("Writing database to stdout with update"),
1499 sh.prg_name,
1500 _("sh_hash_pushdata_int"));
1501 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1502 }
1503
1504 if ((pushdata_stdout == S_TRUE) && (sl_is_suid()))
1505 {
1506 dlog(1, FIL__, __LINE__,
1507 _("You cannot write the database to stdout when running with suid privileges.\n"));
1508 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1509 _("Writing database to stdout when suid"),
1510 sh.prg_name,
1511 _("sh_hash_pushdata_int"));
1512 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1513 }
1514
1515
1516 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) &&
1517 ( (NULL == file_path('D', 'W')) ||
1518 (0 == sl_strcmp(file_path('D', 'W'), _("REQ_FROM_SERVER"))) ))
1519 {
1520 dlog(1, FIL__, __LINE__,
1521 _("You need to configure a local path for initializing the database\nlike ./configure --with-data-file=REQ_FROM_SERVER/some/local/path\n"));
1522 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1523 _("No local path for database specified"),
1524 sh.prg_name,
1525 _("sh_hash_pushdata_int"));
1526 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1527 }
1528
1529
1530 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE))
1531 {
1532 /* Warn that file already exists; file_path != NULL here because
1533 * checked above
1534 */
1535 if (0 == retry_lstat(FIL__, __LINE__, file_path('D', 'W'), &sbuf))
1536 {
1537 if (sh.flag.update == S_FALSE)
1538 {
1539 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_FI_DBEX,
1540 file_path('D', 'W'));
1541 }
1542 }
1543 }
1544
1545
1546 if (sh.flag.update == S_FALSE)
1547 {
1548 if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
1549 {
1550 if ( SL_ISERROR(pushdata_fd = sl_open_write(file_path('D', 'W'), SL_YESPRIV)))
1551 {
1552 SH_FREE(fullpath);
1553 SH_FREE(linkpath);
1554 sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
1555 geteuid(), file_path('D', 'W'));
1556 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1557 }
1558
1559 if (SL_ISERROR(status = sl_lock (pushdata_fd)))
1560 {
1561 SH_FREE(fullpath);
1562 SH_FREE(linkpath);
1563 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1564 _("Failed to lock baseline database"), _("sh_hash_pushdata_int"),
1565 file_path('D', 'W'));
1566 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1567 }
1568
1569 if ( SL_ISERROR(status = sl_forward(pushdata_fd)))
1570 {
1571 SH_FREE(fullpath);
1572 SH_FREE(linkpath);
1573 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1574 _("Failed to seek to end of baseline database"), _("sh_hash_pushdata_int"),
1575 file_path('D', 'W'));
1576 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1577 }
1578 }
1579 }
1580 else /* update == TRUE */
1581 {
1582 if (pushdata_isfirst == 1)
1583 {
1584 TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")))
1585 if ( SL_ISERROR(pushdata_fd = sl_open_rdwr(file_path('D', 'W'), SL_YESPRIV))){
1586 SH_FREE(fullpath);
1587 SH_FREE(linkpath);
1588 sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
1589 geteuid(), file_path('D', 'W'));
1590 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1591 }
1592
1593 if (SL_ISERROR(status = sl_lock (pushdata_fd)))
1594 {
1595 SH_FREE(fullpath);
1596 SH_FREE(linkpath);
1597 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1598 _("Failed to lock baseline database"), _("sh_hash_pushdata_int"),
1599 file_path('D', 'W'));
1600 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1601 }
1602
1603 line = SH_ALLOC(MAX_PATH_STORE+1);
1604 if (SL_ISERROR(sh_hash_setdataent_old (pushdata_fd, line,
1605 MAX_PATH_STORE,
1606 file_path('D', 'W'))))
1607 {
1608 SH_FREE(fullpath);
1609 SH_FREE(linkpath);
1610 SH_FREE(line);
1611 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1612 }
1613 SH_FREE(line);
1614 }
1615 }
1616
1617 if (buf != NULL && buf->fullpath != NULL) {
1618
1619 old_len = sl_strlen(buf->fullpath);
1620#if defined(SH_STEALTH)
1621 sh_do_encode(buf->fullpath, old_len);
1622#endif
1623 tmp = quote_string(buf->fullpath, old_len);
1624 tmp_len = sl_strlen(tmp);
1625#if defined(SH_STEALTH)
1626 sh_do_decode(buf->fullpath, old_len);
1627#endif
1628
1629 if (tmp && tmp_len <= MAX_PATH_STORE)
1630 {
1631 sl_strlcpy(fullpath, buf->fullpath, MAX_PATH_STORE+1);
1632 }
1633 else
1634 {
1635 char hashbuf[KEYBUF_SIZE];
1636
1637 sl_strlcpy(fullpath,
1638 sh_tiger_hash (buf->fullpath,
1639 TIGER_DATA, old_len,
1640 hashbuf, sizeof(hashbuf)),
1641 KEY_LEN+1);
1642 }
1643 if (tmp) SH_FREE(tmp);
1644 }
1645
1646 path_len = sl_strlen(fullpath);
1647#if defined(SH_STEALTH)
1648 sh_do_encode(fullpath, path_len);
1649#endif
1650
1651 tmp = quote_string(fullpath, path_len);
1652 if (tmp) {
1653 sl_strlcpy(fullpath, tmp, MAX_PATH_STORE+1);
1654 SH_FREE(tmp);
1655 }
1656
1657 if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL)
1658 {
1659
1660 old_len = sl_strlen(buf->link_path);
1661#if defined(SH_STEALTH)
1662 if (buf->c_mode[0] == 'l')
1663 sh_do_encode(buf->link_path, old_len);
1664#endif
1665 tmp = quote_string(buf->link_path, old_len);
1666 tmp_len = sl_strlen(tmp);
1667#if defined(SH_STEALTH)
1668 if (buf->c_mode[0] == 'l')
1669 sh_do_decode(buf->link_path, old_len);
1670#endif
1671
1672 if (tmp && tmp_len <= MAX_PATH_STORE)
1673 {
1674 sl_strlcpy(linkpath, buf->link_path, MAX_PATH_STORE+1);
1675 }
1676 else
1677 {
1678 char hashbuf[KEYBUF_SIZE];
1679 sl_strlcpy(linkpath,
1680 sh_tiger_hash (buf->link_path,
1681 TIGER_DATA, old_len,
1682 hashbuf, sizeof(hashbuf)),
1683 KEY_LEN+1);
1684 }
1685 if (tmp) SH_FREE(tmp);
1686
1687 path_len = sl_strlen(linkpath);
1688#if defined(SH_STEALTH)
1689 if (buf->c_mode[0] == 'l')
1690 sh_do_encode(linkpath, path_len);
1691#endif
1692 tmp = quote_string(linkpath, path_len);
1693 if (tmp)
1694 {
1695 sl_strlcpy(linkpath, tmp, MAX_PATH_STORE+1);
1696 SH_FREE(tmp);
1697 }
1698 }
1699
1700 if (buf != NULL && buf->attr_string != NULL)
1701 {
1702 old_len = sl_strlen(buf->attr_string);
1703#if defined(SH_STEALTH)
1704 sh_do_encode(buf->attr_string, old_len);
1705#endif
1706 tmp = quote_string(buf->attr_string, old_len);
1707 if (tmp)
1708 {
1709 attr_string = tmp;
1710 tmp = NULL;
1711 }
1712#if defined(SH_STEALTH)
1713 sh_do_decode(buf->attr_string, old_len);
1714#endif
1715 }
1716
1717
1718 if (buf != NULL) {
1719 p.mark = REC_MAGIC;
1720 if (attr_string)
1721 p.mark |= REC_FLAGS_ATTR;
1722 sl_strlcpy(p.c_mode, buf->c_mode, CMODE_SIZE);
1723 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
1724 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
1725 if (fileHash) {
1726 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
1727 }
1728#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1729 sl_strlcpy(p.c_attributes, buf->c_attributes, ATTRBUF_SIZE);
1730#else
1731 for (i = 0; i < ATTRBUF_USED; ++i) p.c_attributes[i] = '-';
1732 p.c_attributes[ATTRBUF_USED] = '\0';
1733#endif
1734
1735#if defined(SH_STEALTH)
1736 sh_do_encode(p.c_mode, sl_strlen(p.c_mode));
1737 sh_do_encode(p.c_owner, sl_strlen(p.c_owner));
1738 sh_do_encode(p.c_group, sl_strlen(p.c_group));
1739 sh_do_encode(p.checksum, sl_strlen(p.checksum));
1740
1741 sh_do_encode(p.c_attributes, sl_strlen(p.c_attributes));
1742#endif
1743
1744#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1745 p.attributes = (UINT32) buf->attributes;
1746#else
1747 p.attributes = 0;
1748#endif
1749 p.linkmode = (UINT32) buf->linkmode;
1750 p.hardlinks = (UINT32) buf->hardlinks;
1751 p.dev = (UINT64) buf->dev;
1752 p.rdev = (UINT64) buf->rdev;
1753 p.mode = (UINT32) buf->mode;
1754 p.ino = (UINT32) buf->ino;
1755 p.size = (UINT64) buf->size;
1756 p.mtime = (UINT64) buf->mtime;
1757 p.atime = (UINT64) buf->atime;
1758 p.ctime = (UINT64) buf->ctime;
1759 p.owner = (UINT32) buf->owner;
1760 p.group = (UINT32) buf->group;
1761
1762 swap_32(&(p.mode));
1763 swap_32(&(p.linkmode));
1764 swap_64(&(p.dev));
1765 swap_64(&(p.rdev));
1766 swap_32(&(p.hardlinks));
1767 swap_32(&(p.ino));
1768 swap_64(&(p.size));
1769 swap_64(&(p.atime));
1770 swap_64(&(p.mtime));
1771 swap_64(&(p.ctime));
1772 swap_32(&(p.owner));
1773 swap_32(&(p.group));
1774 swap_32(&(p.attributes));
1775
1776#ifdef OLD_BUG
1777 swap_short(&(p.mark));
1778#else
1779 p.mark = *(swap_short(&(p.mark)));
1780#endif
1781 }
1782
1783 /* write the start marker
1784 */
1785 if (pushdata_isfirst == 1)
1786 {
1787 if (sh.flag.update == S_FALSE)
1788 {
1789 if (sh_db_version_string != NULL)
1790 {
1791 if (pushdata_stdout == S_FALSE)
1792 {
1793 sl_write (pushdata_fd, _("\n#Host "), 7);
1794 sl_write (pushdata_fd, sh.host.name,
1795 sl_strlen(sh.host.name));
1796 sl_write (pushdata_fd, _(" Version "), 9);
1797 sl_write (pushdata_fd, sh_db_version_string,
1798 sl_strlen(sh_db_version_string));
1799 sl_write (pushdata_fd, _(" Date "), 6);
1800 (void) sh_unix_time(0, timestring, sizeof(timestring));
1801 sl_write (pushdata_fd, timestring, sl_strlen(timestring));
1802 sl_write (pushdata_fd, "\n", 1);
1803 } else {
1804 printf ("%s",_("\n#Host "));
1805 printf ("%s", sh.host.name);
1806 printf ("%s",_(" Version "));
1807 printf ("%s", sh_db_version_string);
1808 printf ("%s",_(" Date "));
1809 (void) sh_unix_time(0, timestring, sizeof(timestring));
1810 printf ("%s\n", timestring);
1811 }
1812 }
1813
1814 if (pushdata_stdout == S_FALSE)
1815 {
1816#if defined(SH_STEALTH)
1817 sl_write (pushdata_fd, "\n", 1);
1818 sl_write_line (pushdata_fd, N_("[SOF]"), 5);
1819#else
1820 sl_write_line (pushdata_fd, _("\n[SOF]"), 6);
1821#endif
1822 }
1823 else
1824 {
1825#if defined(SH_STEALTH)
1826 printf ("\n%s\n", N_("[SOF]"));
1827#else
1828 printf ("%s\n", _("\n[SOF]"));
1829#endif
1830 }
1831 }
1832 pushdata_isfirst = 0;
1833 }
1834
1835 if (pushdata_stdout == S_FALSE)
1836 {
1837 sl_write (pushdata_fd, &p, sizeof(sh_filestore_t));
1838 sl_write_line_fast (pushdata_fd, fullpath, sl_strlen(fullpath));
1839 sl_write_line_fast (pushdata_fd, linkpath, sl_strlen(linkpath));
1840 if (attr_string)
1841 sl_write_line_fast (pushdata_fd, attr_string, sl_strlen(attr_string));
1842 } else {
1843 if (fwrite (&p, sizeof(sh_filestore_t), 1, stdout))
1844 {
1845 printf ("%s\n", fullpath);
1846 printf ("%s\n", linkpath);
1847 if (attr_string)
1848 printf ("%s\n", attr_string);
1849 }
1850 else
1851 {
1852 perror(_("Error writing database"));
1853 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1854 }
1855 }
1856
1857 ++p_count;
1858
1859 if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
1860 {
1861 if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
1862 {
1863 sl_close (pushdata_fd);
1864 pushdata_fd = -1;
1865 }
1866 }
1867
1868 SH_FREE(fullpath);
1869 SH_FREE(linkpath);
1870 if (attr_string)
1871 SH_FREE(attr_string);
1872
1873 SL_RET0(_("sh_hash_pushdata_int"));
1874}
1875
1876SH_MUTEX_STATIC(mutex_writeout,PTHREAD_MUTEX_INITIALIZER);
1877
1878void sh_hash_pushdata (file_type * buf, char * fileHash)
1879{
1880 SH_MUTEX_LOCK(mutex_writeout);
1881 sh_hash_pushdata_int (buf, fileHash);
1882 SH_MUTEX_UNLOCK(mutex_writeout);
1883 return;
1884}
1885
1886
1887int sh_hash_writeout()
1888{
1889 sh_file_t * p;
1890 int i;
1891 file_type * f;
1892 char fileHash[KEY_LEN + 1];
1893
1894 SL_ENTER(_("sh_hash_writeout"));
1895
1896 if (S_TRUE == file_is_remote())
1897 {
1898 sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN,
1899 _("Baseline database is remote"), _("sh_hash_writeout"));
1900 SL_RETURN (1, _("sh_hash_writeout"));
1901 }
1902
1903 SH_MUTEX_LOCK(mutex_writeout);
1904 if (!SL_ISERROR(pushdata_fd))
1905 {
1906 sl_close(pushdata_fd);
1907 pushdata_fd = -1;
1908 }
1909 pushdata_isfirst = 1;
1910
1911
1912 SH_MUTEX_LOCK(mutex_hash);
1913 for (i = 0; i < TABSIZE; ++i)
1914 {
1915 for (p = tab[i]; p; p = p->next)
1916 {
1917 f = sh_hash_create_ft (p, fileHash);
1918 sh_hash_pushdata_int (f, fileHash);
1919 if (f->attr_string) SH_FREE(f->attr_string);
1920 if (f->link_path) SH_FREE(f->link_path);
1921 SH_FREE(f);
1922 }
1923 }
1924 SH_MUTEX_UNLOCK(mutex_hash);
1925
1926 if (!SL_ISERROR(pushdata_fd))
1927 {
1928 sl_close(pushdata_fd);
1929 pushdata_fd = -1;
1930 }
1931 pushdata_isfirst = 1;
1932 SH_MUTEX_UNLOCK(mutex_writeout);
1933
1934 SL_RETURN (0, _("sh_hash_writeout"));
1935}
1936
1937
1938/*********************************************************************
1939 *
1940 * Check whether a file is present in the database.
1941 *
1942 *********************************************************************/
1943static sh_file_t * sh_hash_have_it_int (char * newname)
1944{
1945 sh_file_t * p;
1946 char hashbuf[KEYBUF_SIZE];
1947
1948 SL_ENTER(_("sh_hash_have_it_int"));
1949
1950 if (newname == NULL)
1951 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
1952
1953 if (sl_strlen(newname) <= MAX_PATH_STORE)
1954 p = hashsearch(newname);
1955 else
1956 p = hashsearch ( sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
1957 hashbuf, sizeof(hashbuf)) );
1958 if (p == NULL)
1959 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
1960
1961 SL_RETURN( (p), _("sh_hash_have_it_int"));
1962}
1963
1964int sh_hash_have_it (char * newname)
1965{
1966 sh_file_t * p;
1967 int retval;
1968
1969 if (IsInit != 1)
1970 sh_hash_init();
1971
1972 SH_MUTEX_LOCK(mutex_hash);
1973
1974 retval = 0;
1975
1976 p = sh_hash_have_it_int (newname);
1977
1978 if (!p)
1979 retval = (-1);
1980 else if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) &&
1981 (p->modi_mask & MODI_CHK) != 0 &&
1982 (p->modi_mask & MODI_MOD) != 0)
1983 retval = 1;
1984 SH_MUTEX_UNLOCK(mutex_hash);
1985
1986 return retval;
1987}
1988
1989int sh_hash_get_it (char * newname, file_type * tmpFile)
1990{
1991 sh_file_t * p;
1992 int retval;
1993
1994 if (IsInit != 1)
1995 sh_hash_init();
1996
1997 tmpFile->link_path = NULL;
1998 tmpFile->attr_string = NULL;
1999
2000 SH_MUTEX_LOCK(mutex_hash);
2001
2002 retval = (-1);
2003
2004 p = sh_hash_have_it_int (newname);
2005 if (p)
2006 {
2007 sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
2008 if (p->linkpath)
2009 tmpFile->link_path = sh_util_strdup (p->linkpath);
2010 tmpFile->size = p->theFile.size;
2011 tmpFile->mtime = p->theFile.mtime;
2012 tmpFile->ctime = p->theFile.ctime;
2013 tmpFile->attr_string = NULL;
2014 retval = 0;
2015 }
2016 SH_MUTEX_UNLOCK(mutex_hash);
2017
2018 return retval;
2019}
2020
2021int sh_hash_getflags (char * filename)
2022{
2023 sh_file_t * p;
2024 int retval;
2025
2026 if (IsInit != 1)
2027 sh_hash_init();
2028
2029 SH_MUTEX_LOCK(mutex_hash);
2030 p = sh_hash_have_it_int (filename);
2031 if (p)
2032 retval = p->fflags;
2033 else
2034 retval = -1;
2035 SH_MUTEX_UNLOCK(mutex_hash);
2036 return retval;
2037}
2038
2039int sh_hash_setflags (char * filename, int flags)
2040{
2041 sh_file_t * p;
2042 int retval;
2043
2044 if (IsInit != 1)
2045 sh_hash_init();
2046
2047 SH_MUTEX_LOCK(mutex_hash);
2048 p = sh_hash_have_it_int (filename);
2049 if (p)
2050 {
2051 p->fflags = flags;
2052 retval = 0;
2053 }
2054 else
2055 retval = -1;
2056 SH_MUTEX_UNLOCK(mutex_hash);
2057 return retval;
2058}
2059
2060/* needs lock to be threadsafe
2061 */
2062void sh_hash_addflag (char * filename, int flag_to_set)
2063{
2064 sh_file_t * p;
2065
2066 if (IsInit != 1)
2067 sh_hash_init();
2068
2069 SH_MUTEX_LOCK(mutex_hash);
2070 p = sh_hash_have_it_int (filename);
2071 if (p)
2072 {
2073 p->fflags |= flag_to_set;
2074 }
2075 SH_MUTEX_UNLOCK(mutex_hash);
2076 return;
2077}
2078
2079/*****************************************************************
2080 *
2081 * Set a file's status to 'visited'. This is required for
2082 * files that should be ignored, and may be present in the
2083 * database, but not on disk.
2084 *
2085 *****************************************************************/
2086static int sh_hash_set_visited_int (char * newname, int flag)
2087{
2088 sh_file_t * p;
2089 char hashbuf[KEYBUF_SIZE];
2090 int retval;
2091
2092 SL_ENTER(_("sh_hash_set_visited_int"));
2093
2094 if (newname == NULL)
2095 SL_RETURN((-1), _("sh_hash_set_visited_int"));
2096
2097 if (IsInit != 1)
2098 sh_hash_init();
2099
2100 SH_MUTEX_LOCK(mutex_hash);
2101
2102 if (sl_strlen(newname) <= MAX_PATH_STORE)
2103 p = hashsearch(newname);
2104 else
2105 p = hashsearch (sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
2106 hashbuf, sizeof(hashbuf)));
2107
2108 if (p)
2109 {
2110 if (flag == SH_FFLAG_CHECKED)
2111 {
2112 CLEAR_SH_FFLAG_REPORTED(p->fflags);
2113 CLEAR_SH_FFLAG_VISITED(p->fflags);
2114 SET_SH_FFLAG_CHECKED(p->fflags);
2115 }
2116 else
2117 {
2118 SET_SH_FFLAG_VISITED(p->fflags);
2119 CLEAR_SH_FFLAG_CHECKED(p->fflags);
2120 if (flag == SH_FFLAG_REPORTED)
2121 SET_SH_FFLAG_REPORTED(p->fflags);
2122 else
2123 CLEAR_SH_FFLAG_REPORTED(p->fflags);
2124 }
2125 retval = 0;
2126 }
2127 else
2128 retval = -1;
2129
2130 SH_MUTEX_UNLOCK(mutex_hash);
2131 SL_RETURN((retval), _("sh_hash_set_visited_int"));
2132}
2133
2134
2135/* cause the record to be deleted without a 'missing' message
2136 */
2137int sh_hash_set_missing (char * newname)
2138{
2139 int i;
2140 SL_ENTER(_("sh_hash_set_visited"));
2141 i = sh_hash_set_visited_int(newname, SH_FFLAG_CHECKED);
2142 SL_RETURN(i, _("sh_hash_set_visited"));
2143}
2144
2145/* mark the file as visited and reported
2146 */
2147int sh_hash_set_visited (char * newname)
2148{
2149 int i;
2150 SL_ENTER(_("sh_hash_set_visited"));
2151 i = sh_hash_set_visited_int(newname, SH_FFLAG_REPORTED);
2152 SL_RETURN(i, _("sh_hash_set_visited"));
2153}
2154
2155/* mark the file as visited and NOT reported
2156 * used to avoid deletion of file from internal database
2157 */
2158int sh_hash_set_visited_true (char * newname)
2159{
2160 int i;
2161 SL_ENTER(_("sh_hash_set_visited_true"));
2162 i = sh_hash_set_visited_int(newname, 0);
2163 SL_RETURN(i, _("sh_hash_set_visited_true"));
2164}
2165
2166
2167/******************************************************************
2168 *
2169 * Data entry for arbitrary data into database
2170 *
2171 ******************************************************************/
2172
2173void sh_hash_push2db (char * key, unsigned long val1,
2174 unsigned long val2, unsigned long val3,
2175 unsigned char * str, int size)
2176{
2177 int i = 0;
2178 char * p;
2179 char i2h[2];
2180 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
2181
2182 tmpFile->attr_string = NULL;
2183 tmpFile->link_path = NULL;
2184
2185 sl_strlcpy(tmpFile->fullpath, key, PATH_MAX);
2186 tmpFile->size = val1;
2187 tmpFile->mtime = val2;
2188 tmpFile->ctime = val3;
2189
2190 tmpFile->atime = 0;
2191 tmpFile->mode = 0;
2192 tmpFile->owner = 0;
2193 tmpFile->group = 0;
2194 sl_strlcpy(tmpFile->c_owner, _("root"), 5);
2195 sl_strlcpy(tmpFile->c_group, _("root"), 5);
2196
2197 if ((str != NULL) && (size < (PATH_MAX/2)-1))
2198 {
2199 tmpFile->c_mode[0] = 'l';
2200 tmpFile->c_mode[1] = 'r'; tmpFile->c_mode[2] = 'w';
2201 tmpFile->c_mode[3] = 'x'; tmpFile->c_mode[4] = 'r';
2202 tmpFile->c_mode[5] = 'w'; tmpFile->c_mode[6] = 'x';
2203 tmpFile->c_mode[7] = 'r'; tmpFile->c_mode[8] = 'w';
2204 tmpFile->c_mode[9] = 'x'; tmpFile->c_mode[10] = '\0';
2205 tmpFile->link_path = SH_ALLOC((size * 2) + 2);
2206 for (i = 0; i < size; ++i)
2207 {
2208 p = sh_util_charhex (str[i],i2h);
2209 tmpFile->link_path[2*i] = p[0];
2210 tmpFile->link_path[2*i+1] = p[1];
2211 tmpFile->link_path[2*i+2] = '\0';
2212 }
2213 }
2214 else
2215 {
2216 for (i = 0; i < 10; ++i)
2217 tmpFile->c_mode[i] = '-';
2218 tmpFile->c_mode[10] = '\0';
2219 tmpFile->link_path = sh_util_strdup("-");
2220 }
2221
2222 if (sh.flag.checkSum == SH_CHECK_CHECK &&
2223 sh.flag.update == S_TRUE)
2224 sh_hash_pushdata_memory (tmpFile, SH_KEY_NULL);
2225 else
2226 sh_hash_pushdata (tmpFile, SH_KEY_NULL);
2227
2228 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
2229 SH_FREE(tmpFile);
2230 return;
2231}
2232
2233extern int sh_util_hextobinary (char * binary, char * hex, int bytes);
2234
2235char * sh_hash_db2pop (char * key, unsigned long * val1,
2236 unsigned long * val2, unsigned long * val3,
2237 int * size)
2238{
2239 size_t len;
2240 char * p;
2241 int i;
2242 char * retval = NULL;
2243 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
2244
2245 *size = 0;
2246
2247 if (0 == sh_hash_get_it (key, tmpFile))
2248 {
2249 *val1 = tmpFile->size;
2250 *val2 = tmpFile->mtime;
2251 *val3 = tmpFile->ctime;
2252
2253 if (tmpFile->link_path && tmpFile->link_path[0] != '-')
2254 {
2255 len = strlen(tmpFile->link_path);
2256
2257 p = SH_ALLOC((len/2)+1);
2258 i = sh_util_hextobinary (p, tmpFile->link_path, len);
2259
2260 if (i == 0)
2261 {
2262 *size = (len/2);
2263 p[*size] = '\0';
2264 retval = p;
2265 }
2266 else
2267 {
2268 SH_FREE(p);
2269 *size = 0;
2270 }
2271 }
2272 else
2273 {
2274 *size = 0;
2275 }
2276 }
2277 else
2278 {
2279 *size = -1;
2280 *val1 = 0;
2281 *val2 = 0;
2282 *val3 = 0;
2283 }
2284 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
2285 SH_FREE(tmpFile);
2286 return retval;
2287}
2288
2289
2290
2291
2292/******************************************************************
2293 *
2294 * Data entry in hash table
2295 *
2296 ******************************************************************/
2297sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
2298{
2299 sh_file_t * fp;
2300 sh_filestore_t p;
2301
2302 size_t len;
2303 char * fullpath;
2304 char * linkpath;
2305 char * attr_string = NULL;
2306 char hashbuf[KEYBUF_SIZE];
2307
2308 SL_ENTER(_("sh_hash_push_int"));
2309
2310 fp = SH_ALLOC(sizeof(sh_file_t));
2311
2312 p.mark = REC_MAGIC;
2313 if (buf->attr_string)
2314 p.mark |= REC_FLAGS_ATTR;
2315 sl_strlcpy(p.c_mode, buf->c_mode, 11);
2316 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
2317 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
2318 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
2319#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2320 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
2321#endif
2322
2323#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2324 p.attributes = (UINT32) buf->attributes;
2325#endif
2326 p.linkmode = (UINT32) buf->linkmode;
2327 p.hardlinks = (UINT32) buf->hardlinks;
2328 p.dev = (UINT64) buf->dev;
2329 p.rdev = (UINT64) buf->rdev;
2330 p.mode = (UINT32) buf->mode;
2331 p.ino = (UINT32) buf->ino;
2332 p.size = (UINT64) buf->size;
2333 p.mtime = (UINT64) buf->mtime;
2334 p.atime = (UINT64) buf->atime;
2335 p.ctime = (UINT64) buf->ctime;
2336 p.owner = (UINT32) buf->owner;
2337 p.group = (UINT32) buf->group;
2338
2339 memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
2340 fp->fflags = 0; /* init fflags */
2341 fp->modi_mask = 0L;
2342
2343 if (buf->attr_string)
2344 attr_string = sh_util_strdup(buf->attr_string);
2345 fp->attr_string = attr_string;
2346
2347 len = sl_strlen(buf->fullpath);
2348 if (len <= MAX_PATH_STORE)
2349 {
2350 fullpath = SH_ALLOC(len+1);
2351 sl_strlcpy(fullpath, buf->fullpath, len+1);
2352 }
2353 else
2354 {
2355 fullpath = SH_ALLOC(KEY_LEN + 1);
2356 sl_strlcpy(fullpath,
2357 sh_tiger_hash (buf->fullpath, TIGER_DATA, len,
2358 hashbuf, sizeof(hashbuf)),
2359 KEY_LEN+1);
2360 }
2361 fp->fullpath = fullpath;
2362
2363 if (buf->link_path)
2364 {
2365 len = sl_strlen(buf->link_path);
2366 if (len <= MAX_PATH_STORE)
2367 {
2368 linkpath = SH_ALLOC(len+1);
2369 sl_strlcpy(linkpath, buf->link_path, len+1);
2370 }
2371 else
2372 {
2373 linkpath = SH_ALLOC(KEY_LEN + 1);
2374 sl_strlcpy(linkpath,
2375 sh_tiger_hash (buf->link_path, TIGER_DATA, len,
2376 hashbuf, sizeof(hashbuf)),
2377 KEY_LEN+1);
2378 }
2379 fp->linkpath = linkpath;
2380 }
2381 else
2382 fp->linkpath = NULL;
2383
2384 SL_RETURN( fp, _("sh_hash_push_int"));
2385}
2386
2387#ifdef HAVE_INTTYPES_H
2388#include <inttypes.h>
2389#else
2390#ifdef HAVE_STDINT_H
2391#include <stdint.h>
2392#endif
2393#endif
2394
2395#ifndef PRIu64
2396#ifdef HAVE_LONG_32
2397#define PRIu64 "llu"
2398#else
2399#define PRIu64 "lu"
2400#endif
2401#endif
2402
2403char * sh_hash_size_format()
2404{
2405 static char form_rval[81];
2406
2407 SL_ENTER(_("sh_hash_size_format"));
2408
2409
2410#ifdef SH_USE_XML
2411 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2412 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
2413#else
2414 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2415 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
2416#endif
2417
2418 SL_RETURN( form_rval, _("sh_hash_size_format"));
2419}
2420
2421
2422#ifdef SH_USE_XML
2423static char * all_items (file_type * theFile, char * fileHash, int is_new)
2424{
2425 char timstr1c[32];
2426 char timstr1a[32];
2427 char timstr1m[32];
2428
2429 char * tmp_lnk;
2430 char * format;
2431
2432 char * tmp = SH_ALLOC(SH_MSG_BUF);
2433 char * msg = SH_ALLOC(SH_MSG_BUF);
2434
2435 tmp[0] = '\0';
2436 msg[0] = '\0';
2437
2438
2439#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2440 if (is_new)
2441 format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" ");
2442 else
2443 format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" ");
2444 sl_snprintf(tmp, SH_MSG_BUF, format,
2445 theFile->c_mode,
2446 theFile->c_attributes,
2447 (long) theFile->mode,
2448 (long) theFile->attributes
2449 );
2450#else
2451 if (is_new)
2452 format = _("mode_new=\"%s\" imode_new=\"%ld\" ");
2453 else
2454 format = _("mode_old=\"%s\" imode_old=\"%ld\" ");
2455
2456 sl_snprintf(tmp, SH_MSG_BUF, format,
2457 theFile->c_mode,
2458 (long) theFile->mode
2459 );
2460#endif
2461 sl_strlcat(msg, tmp, SH_MSG_BUF);
2462
2463 if (is_new)
2464 format = _("hardlinks_new=\"%lu\" ");
2465 else
2466 format = _("hardlinks_old=\"%lu\" ");
2467 sl_snprintf(tmp, SH_MSG_BUF, format,
2468 (unsigned long) theFile->hardlinks);
2469 sl_strlcat(msg, tmp, SH_MSG_BUF);
2470
2471
2472 if (is_new)
2473 format = _("idevice_new=\"%lu\" ");
2474 else
2475 format = _("idevice_old=\"%lu\" ");
2476 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2477 sl_strlcat(msg, tmp, SH_MSG_BUF);
2478
2479
2480 if (is_new)
2481 format = _("inode_new=\"%lu\" ");
2482 else
2483 format = _("inode_old=\"%lu\" ");
2484 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2485 sl_strlcat(msg, tmp, SH_MSG_BUF);
2486
2487 /*
2488 * also report device for prelude
2489 */
2490#if defined(HAVE_LIBPRELUDE)
2491 if (is_new)
2492 format = _("dev_new=\"%lu,%lu\" ");
2493 else
2494 format = _("dev_old=\"%lu,%lu\" ");
2495 sl_snprintf(tmp, SH_MSG_BUF, format,
2496 (unsigned long) major(theFile->dev),
2497 (unsigned long) minor(theFile->dev));
2498 sl_strlcat(msg, tmp, SH_MSG_BUF);
2499#endif
2500
2501
2502 if (is_new)
2503 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
2504 else
2505 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
2506 sl_snprintf(tmp, SH_MSG_BUF, format,
2507 theFile->c_owner, (long) theFile->owner);
2508 sl_strlcat(msg, tmp, SH_MSG_BUF);
2509
2510
2511 if (is_new)
2512 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
2513 else
2514 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
2515 sl_snprintf(tmp, SH_MSG_BUF, format,
2516 theFile->c_group, (long) theFile->group);
2517 sl_strlcat(msg, tmp, SH_MSG_BUF);
2518
2519
2520 if (is_new)
2521 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2522 (UINT64) 0, (UINT64) theFile->size);
2523 else
2524 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2525 (UINT64) theFile->size, (UINT64) 0);
2526 sl_strlcat(msg, tmp, SH_MSG_BUF);
2527
2528
2529 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2530 if (is_new)
2531 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=\"%s\" "), timstr1c);
2532 else
2533 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" "), timstr1c);
2534 sl_strlcat(msg, tmp, SH_MSG_BUF);
2535
2536 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2537 if (is_new)
2538 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=\"%s\" "), timstr1a);
2539 else
2540 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" "), timstr1a);
2541 sl_strlcat(msg, tmp, SH_MSG_BUF);
2542
2543 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2544 if (is_new)
2545 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=\"%s\" "), timstr1m);
2546 else
2547 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" "), timstr1m);
2548 sl_strlcat(msg, tmp, SH_MSG_BUF);
2549
2550 if (is_new)
2551 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=\"%s\" "), fileHash);
2552 else
2553 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=\"%s\" "), fileHash);
2554 sl_strlcat(msg, tmp, SH_MSG_BUF);
2555
2556 if (theFile->c_mode[0] == 'l' ||
2557 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
2558 {
2559 tmp_lnk = sh_util_safe_name(theFile->link_path);
2560 if (tmp_lnk)
2561 {
2562 if (is_new)
2563 sl_snprintf(tmp, SH_MSG_BUF, _("link_new=\"%s\" "), tmp_lnk);
2564 else
2565 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" "), tmp_lnk);
2566 SH_FREE(tmp_lnk);
2567 sl_strlcat(msg, tmp, SH_MSG_BUF);
2568 }
2569 }
2570
2571 if (theFile->attr_string)
2572 {
2573 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2574 if (tmp_lnk)
2575 {
2576 if (is_new)
2577 sl_snprintf(tmp, SH_MSG_BUF, _("acl_new=\"%s\" "), tmp_lnk);
2578 else
2579 sl_snprintf(tmp, SH_MSG_BUF, _("acl_old=\"%s\" "), tmp_lnk);
2580 SH_FREE(tmp_lnk);
2581 sl_strlcat(msg, tmp, SH_MSG_BUF);
2582 }
2583 }
2584
2585
2586 SH_FREE(tmp);
2587 return (msg);
2588}
2589#else
2590static char * all_items (file_type * theFile, char * fileHash, int is_new)
2591{
2592 char timstr1c[32];
2593 char timstr1a[32];
2594 char timstr1m[32];
2595
2596 char * tmp_lnk;
2597 char * format;
2598
2599 char * tmp = SH_ALLOC(SH_MSG_BUF);
2600 char * msg = SH_ALLOC(SH_MSG_BUF);
2601
2602 tmp[0] = '\0';
2603 msg[0] = '\0';
2604
2605
2606#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2607 if (is_new)
2608 format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, ");
2609 else
2610 format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, ");
2611 sl_snprintf(tmp, SH_MSG_BUF, format,
2612 theFile->c_mode,
2613 theFile->c_attributes,
2614 (long) theFile->mode,
2615 (long) theFile->attributes
2616 );
2617#else
2618 if (is_new)
2619 format = _("mode_new=<%s>, imode_new=<%ld>, ");
2620 else
2621 format = _("mode_old=<%s>, imode_old=<%ld>, ");
2622
2623 sl_snprintf(tmp, SH_MSG_BUF, format,
2624 theFile->c_mode,
2625 (long) theFile->mode
2626 );
2627#endif
2628 sl_strlcat(msg, tmp, SH_MSG_BUF);
2629
2630 if (is_new)
2631 format = _("hardlinks_new=<%lu>, ");
2632 else
2633 format = _("hardlinks_old=<%lu>, ");
2634 sl_snprintf(tmp, SH_MSG_BUF, format,
2635 (unsigned long) theFile->hardlinks);
2636 sl_strlcat(msg, tmp, SH_MSG_BUF);
2637
2638
2639 if (is_new)
2640 format = _("idevice_new=<%lu>, ");
2641 else
2642 format = _("idevice_old=<%lu>, ");
2643 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2644 sl_strlcat(msg, tmp, SH_MSG_BUF);
2645
2646
2647 if (is_new)
2648 format = _("inode_new=<%lu>, ");
2649 else
2650 format = _("inode_old=<%lu>, ");
2651 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2652 sl_strlcat(msg, tmp, SH_MSG_BUF);
2653
2654
2655 /*
2656 * also report device for prelude
2657 */
2658#if defined(HAVE_LIBPRELUDE)
2659 if (is_new)
2660 format = _("dev_new=<%lu,%lu>, ");
2661 else
2662 format = _("dev_old=<%lu,%lu>, ");
2663 sl_snprintf(tmp, SH_MSG_BUF, format,
2664 (unsigned long) major(theFile->dev),
2665 (unsigned long) minor(theFile->dev));
2666 sl_strlcat(msg, tmp, SH_MSG_BUF);
2667#endif
2668
2669 if (is_new)
2670 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
2671 else
2672 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
2673 sl_snprintf(tmp, SH_MSG_BUF, format,
2674 theFile->c_owner, (long) theFile->owner);
2675 sl_strlcat(msg, tmp, SH_MSG_BUF);
2676
2677
2678 if (is_new)
2679 format = _("group_new=<%s>, igroup_new=<%ld>, ");
2680 else
2681 format = _("group_old=<%s>, igroup_old=<%ld>, ");
2682 sl_snprintf(tmp, SH_MSG_BUF, format,
2683 theFile->c_group, (long) theFile->group);
2684 sl_strlcat(msg, tmp, SH_MSG_BUF);
2685
2686
2687 if (is_new)
2688 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2689 (UINT64) 0, (UINT64) theFile->size);
2690 else
2691 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2692 (UINT64) theFile->size, (UINT64) 0);
2693 sl_strlcat(msg, tmp, SH_MSG_BUF);
2694
2695
2696 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2697 if (is_new)
2698 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=<%s>, "), timstr1c);
2699 else
2700 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, "), timstr1c);
2701 sl_strlcat(msg, tmp, SH_MSG_BUF);
2702
2703 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2704 if (is_new)
2705 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=<%s>, "), timstr1a);
2706 else
2707 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, "), timstr1a);
2708 sl_strlcat(msg, tmp, SH_MSG_BUF);
2709
2710 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2711 if (is_new)
2712 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=<%s>, "), timstr1m);
2713 else
2714 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, "), timstr1m);
2715 sl_strlcat(msg, tmp, SH_MSG_BUF);
2716
2717 if (is_new)
2718 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=<%s>"), fileHash);
2719 else
2720 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=<%s>"), fileHash);
2721 sl_strlcat(msg, tmp, SH_MSG_BUF);
2722
2723 if (theFile->c_mode[0] == 'l' ||
2724 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
2725 {
2726 tmp_lnk = sh_util_safe_name(theFile->link_path);
2727 if (tmp_lnk)
2728 {
2729 if (is_new)
2730 sl_snprintf(tmp, SH_MSG_BUF, _(", link_new=<%s> "), tmp_lnk);
2731 else
2732 sl_snprintf(tmp, SH_MSG_BUF, _(", link_old=<%s> "), tmp_lnk);
2733 SH_FREE(tmp_lnk);
2734 sl_strlcat(msg, tmp, SH_MSG_BUF);
2735 }
2736 }
2737
2738 if (theFile->attr_string)
2739 {
2740 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2741 if (tmp_lnk)
2742 {
2743 if (is_new)
2744 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_new=<%s> "), tmp_lnk);
2745 else
2746 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_old=<%s> "), tmp_lnk);
2747 SH_FREE(tmp_lnk);
2748 sl_strlcat(msg, tmp, SH_MSG_BUF);
2749 }
2750 }
2751
2752 SH_FREE(tmp);
2753 return (msg);
2754}
2755#endif
2756
2757void sh_hash_pushdata_memory (file_type * theFile, char * fileHash)
2758{
2759 sh_file_t * p;
2760
2761 SL_ENTER(_("sh_hash_pushdata_memory"));
2762
2763 p = sh_hash_push_int(theFile, fileHash);
2764 if (p)
2765 {
2766 SH_MUTEX_LOCK(mutex_hash);
2767 hashinsert (p);
2768 p->modi_mask = theFile->check_mask;
2769 SH_MUTEX_UNLOCK(mutex_hash);
2770 }
2771
2772 SL_RET0(_("sh_hash_pushdata_memory"));
2773}
2774
2775
2776/*****************************************************************
2777 *
2778 * Compare a file with the database status.
2779 *
2780 *****************************************************************/
2781int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
2782 char * policy_override, int severity_override)
2783{
2784 char * msg;
2785 sh_file_t * p;
2786 char * tmp;
2787 char * tmp_path;
2788 char * tmp_lnk;
2789 char * tmp_lnk_old;
2790
2791 char * str;
2792
2793 char timstr1c[32];
2794 char timstr2c[32];
2795 char timstr1a[32];
2796 char timstr2a[32];
2797 char timstr1m[32];
2798 char timstr2m[32];
2799 char linkHash[KEY_LEN+1];
2800 char * linkComp;
2801 int maxcomp;
2802
2803 char change_code[16];
2804 int i;
2805
2806 unsigned long modi_mask;
2807
2808 char log_policy[32];
2809 volatile int log_severity;
2810 char hashbuf[KEYBUF_SIZE];
2811
2812 int retval;
2813
2814 SL_ENTER(_("sh_hash_compdata"));
2815
2816 if (IsInit != 1) sh_hash_init();
2817
2818 if (severity_override < 0)
2819 log_severity = ShDFLevel[class];
2820 else
2821 log_severity = severity_override;
2822
2823 if (policy_override != NULL)
2824 sl_strlcpy (log_policy, policy_override, 32);
2825
2826 /* -------- find the entry for the file ---------------- */
2827
2828 SH_MUTEX_LOCK(mutex_hash);
2829
2830 modi_mask = 0;
2831 retval = 0;
2832
2833 if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE)
2834 p = hashsearch(theFile->fullpath);
2835 else
2836 p = hashsearch( sh_tiger_hash(theFile->fullpath,
2837 TIGER_DATA,
2838 sl_strlen(theFile->fullpath),
2839 hashbuf, sizeof(hashbuf))
2840 );
2841
2842
2843 /* --------- Not found in database. ------------
2844 */
2845
2846 if (p == NULL)
2847 {
2848 if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
2849 {
2850 tmp = sh_util_safe_name(theFile->fullpath);
2851
2852 str = all_items (theFile, fileHash, 1);
2853 sh_error_handle (log_severity, FIL__, __LINE__, 0,
2854 MSG_FI_ADD2,
2855 tmp, str);
2856 SH_FREE(str);
2857
2858 SH_FREE(tmp);
2859 }
2860
2861 if (sh.flag.reportonce == S_TRUE)
2862 SET_SH_FFLAG_REPORTED(theFile->file_reported);
2863
2864 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2865 {
2866 p = sh_hash_push_int(theFile, fileHash);
2867 if (p)
2868 {
2869 hashinsert (p);
2870 p->modi_mask = theFile->check_mask;
2871 }
2872 }
2873
2874 else if (S_TRUE == sh.flag.update)
2875 {
2876 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
2877 {
2878 p = sh_hash_push_int(theFile, fileHash);
2879 if (p)
2880 {
2881 hashinsert (p);
2882 p->modi_mask = theFile->check_mask;
2883 }
2884 }
2885 else
2886 {
2887 retval = 1;
2888 goto unlock_and_return;
2889 }
2890 }
2891
2892 goto unlock_and_return;
2893 }
2894
2895 p->modi_mask = theFile->check_mask;
2896
2897 /* initialize change_code */
2898 for (i = 0; i < 15; ++i)
2899 change_code[i] = '-';
2900 change_code[15] = '\0';
2901
2902 TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"),
2903 theFile->fullpath, fileHash, p->theFile.checksum));
2904
2905 if ( (fileHash != NULL) && (p->theFile.checksum != NULL) &&
2906 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
2907 (theFile->check_mask & MODI_CHK) != 0)
2908 {
2909 if ((theFile->check_mask & MODI_SGROW) == 0)
2910 {
2911 modi_mask |= MODI_CHK;
2912 change_code[0] = 'C';
2913 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
2914 }
2915 else
2916 {
2917 if (0 != strncmp (&fileHash[KEY_LEN + 1],
2918 p->theFile.checksum, KEY_LEN))
2919 {
2920 modi_mask |= MODI_CHK;
2921 change_code[0] = 'C';
2922 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
2923 }
2924 else
2925 {
2926 p->theFile.size = theFile->size;
2927 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2928 }
2929 }
2930 }
2931
2932 if (p->theFile.c_mode[0] == 'l')
2933 {
2934 if (!(theFile->link_path) &&
2935 (theFile->check_mask & MODI_LNK) != 0)
2936 {
2937 linkComp = NULL;
2938 modi_mask |= MODI_LNK;
2939 change_code[1] = 'L';
2940 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2941 }
2942 else
2943 {
2944 if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE)
2945 {
2946 sl_strlcpy(linkHash,
2947 sh_tiger_hash(theFile->link_path,
2948 TIGER_DATA,
2949 sl_strlen(theFile->link_path),
2950 hashbuf, sizeof(hashbuf)),
2951 MAX_PATH_STORE+1);
2952 linkComp = linkHash;
2953 maxcomp = KEY_LEN;
2954 }
2955 else
2956 {
2957 linkComp = theFile->link_path;
2958 maxcomp = MAX_PATH_STORE;
2959 }
2960
2961 if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 &&
2962 (theFile->check_mask & MODI_LNK) != 0)
2963 {
2964 modi_mask |= MODI_LNK;
2965 change_code[1] = 'L';
2966 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2967 }
2968 }
2969 }
2970
2971 if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b')
2972 {
2973 if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) ||
2974 minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
2975 (theFile->check_mask & MODI_RDEV) != 0)
2976 {
2977 modi_mask |= MODI_RDEV;
2978 change_code[2] = 'D';
2979 TPT ((0, FIL__, __LINE__, _("mod=<rdev>")));
2980 }
2981 }
2982
2983 /* cast to UINT32 in case ino_t is not 32bit
2984 */
2985 if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino &&
2986 (theFile->check_mask & MODI_INO) != 0)
2987 {
2988 modi_mask |= MODI_INO;
2989 change_code[3] = 'I';
2990 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2991 }
2992
2993 if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
2994 (theFile->check_mask & MODI_HLN) != 0)
2995 {
2996 modi_mask |= MODI_HLN;
2997 change_code[4] = 'H';
2998 TPT ((0, FIL__, __LINE__, _("mod=<hardlink>")));
2999 }
3000
3001
3002 if ( ( (theFile->mode != p->theFile.mode)
3003#if defined(USE_ACL) || defined(USE_XATTR)
3004 || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
3005 (
3006 (theFile->attr_string == NULL && p->attr_string != NULL) ||
3007 (theFile->attr_string != NULL && p->attr_string == NULL) ||
3008 (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
3009 )
3010 )
3011#endif
3012#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3013 || (theFile->attributes != p->theFile.attributes)
3014#endif
3015 )
3016 && (theFile->check_mask & MODI_MOD) != 0)
3017 {
3018 modi_mask |= MODI_MOD;
3019 change_code[5] = 'M';
3020 TPT ((0, FIL__, __LINE__, _("mod=<mode>")));
3021 /*
3022 * report link path if switch link/no link
3023 */
3024 if ((theFile->check_mask & MODI_LNK) != 0 &&
3025 (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
3026 (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
3027 {
3028 modi_mask |= MODI_LNK;
3029 change_code[1] = 'L';
3030 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
3031 }
3032 }
3033
3034 if ( theFile->owner != (uid_t) p->theFile.owner &&
3035 (theFile->check_mask & MODI_USR) != 0)
3036 {
3037 modi_mask |= MODI_USR;
3038 change_code[6] = 'U';
3039 TPT ((0, FIL__, __LINE__, _("mod=<user>")));
3040 }
3041
3042 if ( theFile->group != (gid_t) p->theFile.group &&
3043 (theFile->check_mask & MODI_GRP) != 0)
3044 {
3045 modi_mask |= MODI_GRP;
3046 change_code[7] = 'G';
3047 TPT ((0, FIL__, __LINE__, _("mod=<group>")));
3048 }
3049
3050
3051 if ( theFile->mtime != (time_t) p->theFile.mtime &&
3052 (theFile->check_mask & MODI_MTM) != 0)
3053 {
3054 modi_mask |= MODI_MTM;
3055 change_code[8] = 'T';
3056 TPT ((0, FIL__, __LINE__, _("mod=<mtime>")));
3057 }
3058
3059 if ( (theFile->check_mask & MODI_ATM) != 0 &&
3060 theFile->atime != (time_t) p->theFile.atime)
3061 {
3062 modi_mask |= MODI_ATM;
3063 change_code[8] = 'T';
3064 TPT ((0, FIL__, __LINE__, _("mod=<atime>")));
3065 }
3066
3067
3068 /* Resetting the access time will set a new ctime. Thus, either we ignore
3069 * the access time or the ctime for NOIGNORE
3070 */
3071 if ( theFile->ctime != (time_t) p->theFile.ctime &&
3072 (theFile->check_mask & MODI_CTM) != 0)
3073 {
3074 modi_mask |= MODI_CTM;
3075 change_code[8] = 'T';
3076 TPT ((0, FIL__, __LINE__, _("mod=<ctime>")));
3077 }
3078
3079 if ( theFile->size != (off_t) p->theFile.size &&
3080 (theFile->check_mask & MODI_SIZ) != 0)
3081 {
3082 if ((theFile->check_mask & MODI_SGROW) == 0 ||
3083 theFile->size < (off_t) p->theFile.size)
3084 {
3085 modi_mask |= MODI_SIZ;
3086 change_code[9] = 'S';
3087 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
3088 }
3089 }
3090 change_code[10] = '\0';
3091
3092 /* --- Directories special case ---
3093 */
3094 if (p->theFile.c_mode[0] == 'd' &&
3095 0 == (modi_mask & ~(MODI_SIZ|MODI_ATM|MODI_CTM|MODI_MTM)) &&
3096 sh_loosedircheck == S_TRUE)
3097 {
3098 modi_mask = 0;
3099 }
3100
3101 /* --- Report full details. ---
3102 */
3103 if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
3104 {
3105 if ((theFile->check_mask & MODI_ATM) == 0)
3106 modi_mask = MASK_READONLY_;
3107 else
3108 modi_mask = MASK_NOIGNORE_;
3109 }
3110
3111 /* --- Report on modified files. ---
3112 */
3113 if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
3114 {
3115 tmp = SH_ALLOC(SH_MSG_BUF);
3116 msg = SH_ALLOC(SH_MSG_BUF);
3117 msg[0] = '\0';
3118
3119 if ( ((modi_mask & MODI_MOD) != 0)
3120#if defined(HAVE_LIBPRELUDE)
3121 || ((modi_mask & MODI_USR) != 0)
3122 || ((modi_mask & MODI_GRP) != 0)
3123#endif
3124 )
3125 {
3126#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3127 sl_snprintf(tmp, SH_MSG_BUF,
3128#ifdef SH_USE_XML
3129 _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "),
3130#else
3131 _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "),
3132#endif
3133 p->theFile.c_mode, theFile->c_mode,
3134 p->theFile.c_attributes, theFile->c_attributes
3135#ifdef SH_USE_XML
3136 , (long) p->theFile.mode, (long) theFile->mode,
3137 (long) p->theFile.attributes,
3138 (long) theFile->attributes
3139#endif
3140 );
3141#else
3142#ifdef SH_USE_XML
3143 sl_snprintf(tmp, SH_MSG_BUF,
3144 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
3145 p->theFile.c_mode, theFile->c_mode,
3146 (long) p->theFile.mode, (long) theFile->mode);
3147#else
3148 sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=<%s>, mode_new=<%s>, "),
3149 p->theFile.c_mode, theFile->c_mode);
3150#endif
3151#endif
3152 sl_strlcat(msg, tmp, SH_MSG_BUF);
3153
3154#if defined(USE_ACL) || defined(USE_XATTR)
3155 if (theFile->attr_string != NULL || p->attr_string != NULL)
3156 {
3157 sl_snprintf(tmp, SH_MSG_BUF,
3158#ifdef SH_USE_XML
3159 _("acl_old=\"%s\" acl_new=\"%s\" "),
3160#else
3161 _("acl_old=<%s>, acl_new=<%s>, "),
3162#endif
3163 (p->attr_string) ? p->attr_string : _("none"),
3164 (theFile->attr_string) ? theFile->attr_string : _("none"));
3165
3166 sl_strlcat(msg, tmp, SH_MSG_BUF);
3167 }
3168#endif
3169
3170#ifdef REPLACE_OLD
3171 if ((modi_mask & MODI_MOD) != 0)
3172 {
3173 /*
3174 * We postpone update if sh.flag.update == S_TRUE because
3175 * in interactive mode the user may not accept the change.
3176 */
3177 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3178 {
3179 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3180 p->theFile.mode = theFile->mode;
3181#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3182 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
3183 p->theFile.attributes = theFile->attributes;
3184#endif
3185#if defined(USE_ACL) || defined(USE_XATTR)
3186 if (p->attr_string == NULL && theFile->attr_string != NULL)
3187 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3188 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3189 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3190 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3191 {
3192 if (0 != strcmp(theFile->attr_string, p->attr_string))
3193 {
3194 SH_FREE(p->attr_string);
3195 p->attr_string = sh_util_strdup (theFile->attr_string);
3196 }
3197 }
3198#endif
3199 }
3200 }
3201#endif
3202 }
3203
3204 if ((modi_mask & MODI_HLN) != 0)
3205 {
3206 sl_snprintf(tmp, SH_MSG_BUF,
3207#ifdef SH_USE_XML
3208 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
3209#else
3210 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
3211#endif
3212 (unsigned long) p->theFile.hardlinks,
3213 (unsigned long) theFile->hardlinks);
3214 sl_strlcat(msg, tmp, SH_MSG_BUF);
3215#ifdef REPLACE_OLD
3216 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3217 p->theFile.hardlinks = theFile->hardlinks;
3218#endif
3219 }
3220
3221 if ((modi_mask & MODI_RDEV) != 0)
3222 {
3223 sl_snprintf(tmp, SH_MSG_BUF,
3224#ifdef SH_USE_XML
3225 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
3226#else
3227 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
3228#endif
3229 (unsigned long) major(p->theFile.rdev),
3230 (unsigned long) minor(p->theFile.rdev),
3231 (unsigned long) major(theFile->rdev),
3232 (unsigned long) minor(theFile->rdev)
3233#ifdef SH_USE_XML
3234 , (unsigned long) p->theFile.rdev,
3235 (unsigned long) theFile->rdev
3236#endif
3237 );
3238 sl_strlcat(msg, tmp, SH_MSG_BUF);
3239#ifdef REPLACE_OLD
3240 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3241 p->theFile.rdev = theFile->rdev;
3242#endif
3243 }
3244
3245 if ((modi_mask & MODI_INO) != 0)
3246 {
3247 sl_snprintf(tmp, SH_MSG_BUF,
3248#ifdef SH_USE_XML
3249 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
3250#else
3251 _("inode_old=<%lu>, inode_new=<%lu>, "),
3252#endif
3253 (unsigned long) p->theFile.ino,
3254 (unsigned long) theFile->ino);
3255 sl_strlcat(msg, tmp, SH_MSG_BUF);
3256#ifdef REPLACE_OLD
3257 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3258 {
3259 p->theFile.ino = theFile->ino;
3260 p->theFile.dev = theFile->dev;
3261 }
3262#endif
3263 }
3264
3265
3266 /*
3267 * also report device for prelude
3268 */
3269#if defined(HAVE_LIBPRELUDE)
3270 if ((modi_mask & MODI_INO) != 0)
3271 {
3272 sl_snprintf(tmp, SH_MSG_BUF,
3273#ifdef SH_USE_XML
3274 _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "),
3275#else
3276 _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "),
3277#endif
3278 (unsigned long) major(p->theFile.dev),
3279 (unsigned long) minor(p->theFile.dev),
3280 (unsigned long) major(theFile->dev),
3281 (unsigned long) minor(theFile->dev)
3282 );
3283 sl_strlcat(msg, tmp, SH_MSG_BUF);
3284#ifdef REPLACE_OLD
3285 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3286 p->theFile.dev = theFile->dev;
3287#endif
3288 }
3289#endif
3290
3291 if ( ((modi_mask & MODI_USR) != 0)
3292#if defined(HAVE_LIBPRELUDE)
3293 || ((modi_mask & MODI_MOD) != 0)
3294#endif
3295 )
3296 {
3297#ifdef SH_USE_XML
3298 sl_snprintf(tmp, SH_MSG_BUF,
3299 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
3300#else
3301 sl_snprintf(tmp, SH_MSG_BUF,
3302 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
3303#endif
3304 p->theFile.c_owner, theFile->c_owner,
3305 (long) p->theFile.owner, (long) theFile->owner
3306 );
3307 sl_strlcat(msg, tmp, SH_MSG_BUF);
3308#ifdef REPLACE_OLD
3309 if ((modi_mask & MODI_USR) != 0) {
3310 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3311 {
3312 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3313 p->theFile.owner = theFile->owner;
3314 }
3315 }
3316#endif
3317 }
3318
3319 if ( ((modi_mask & MODI_GRP) != 0)
3320#if defined(HAVE_LIBPRELUDE)
3321 || ((modi_mask & MODI_MOD) != 0)
3322#endif
3323 )
3324 {
3325#ifdef SH_USE_XML
3326 sl_snprintf(tmp, SH_MSG_BUF,
3327 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
3328 p->theFile.c_group, theFile->c_group,
3329 (long) p->theFile.group, (long) theFile->group);
3330#else
3331 sl_snprintf(tmp, SH_MSG_BUF,
3332 _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "),
3333 p->theFile.c_group, theFile->c_group,
3334 (long) p->theFile.group, (long) theFile->group);
3335#endif
3336
3337 sl_strlcat(msg, tmp, SH_MSG_BUF);
3338#ifdef REPLACE_OLD
3339 if ((modi_mask & MODI_GRP) != 0) {
3340 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3341 {
3342 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3343 p->theFile.group = theFile->group;
3344 }
3345 }
3346#endif
3347 }
3348
3349 if ((modi_mask & MODI_SIZ) != 0)
3350 {
3351 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
3352 (UINT64) p->theFile.size,
3353 (UINT64) theFile->size);
3354 sl_strlcat(msg, tmp, SH_MSG_BUF);
3355#ifdef REPLACE_OLD
3356 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3357 p->theFile.size = theFile->size;
3358#endif
3359 }
3360
3361 if ((modi_mask & MODI_CTM) != 0)
3362 {
3363 (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c));
3364 (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c));
3365#ifdef SH_USE_XML
3366 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
3367 timstr1c, timstr2c);
3368#else
3369 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, ctime_new=<%s>, "),
3370 timstr1c, timstr2c);
3371#endif
3372 sl_strlcat(msg, tmp, SH_MSG_BUF);
3373#ifdef REPLACE_OLD
3374 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3375 p->theFile.ctime = theFile->ctime;
3376#endif
3377 }
3378
3379 if ((modi_mask & MODI_ATM) != 0)
3380 {
3381 (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a));
3382 (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a));
3383#ifdef SH_USE_XML
3384 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" atime_new=\"%s\" "),
3385 timstr1a, timstr2a);
3386#else
3387 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, atime_new=<%s>, "),
3388 timstr1a, timstr2a);
3389#endif
3390 sl_strlcat(msg, tmp, SH_MSG_BUF);
3391#ifdef REPLACE_OLD
3392 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3393 p->theFile.atime = theFile->atime;
3394#endif
3395 }
3396
3397 if ((modi_mask & MODI_MTM) != 0)
3398 {
3399 (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m));
3400 (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m));
3401#ifdef SH_USE_XML
3402 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
3403 timstr1m, timstr2m);
3404#else
3405 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, mtime_new=<%s>, "),
3406 timstr1m, timstr2m);
3407#endif
3408 sl_strlcat(msg, tmp, SH_MSG_BUF);
3409#ifdef REPLACE_OLD
3410 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3411 p->theFile.mtime = theFile->mtime;
3412#endif
3413 }
3414
3415
3416 if ((modi_mask & MODI_CHK) != 0)
3417 {
3418 sl_snprintf(tmp, SH_MSG_BUF,
3419#ifdef SH_USE_XML
3420 _("chksum_old=\"%s\" chksum_new=\"%s\" "),
3421#else
3422 _("chksum_old=<%s>, chksum_new=<%s>, "),
3423#endif
3424 p->theFile.checksum, fileHash);
3425 sl_strlcat(msg, tmp, SH_MSG_BUF);
3426#ifdef REPLACE_OLD
3427 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3428 {
3429 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3430 if ((theFile->check_mask & MODI_SGROW) != 0)
3431 p->theFile.size = theFile->size;
3432 }
3433#endif
3434 /* FIXME is this correct? */
3435 if (theFile->c_mode[0] != 'l' && theFile->link_path &&
3436 strlen(theFile->link_path) > 2)
3437 modi_mask |= MODI_LNK;
3438 }
3439
3440
3441 if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */)
3442 {
3443 if (theFile->link_path)
3444 tmp_lnk = sh_util_safe_name(theFile->link_path);
3445 else
3446 tmp_lnk = sh_util_strdup("-");
3447 if (p->linkpath)
3448 tmp_lnk_old = sh_util_safe_name(p->linkpath);
3449 else
3450 tmp_lnk_old = sh_util_strdup("-");
3451#ifdef SH_USE_XML
3452 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" link_new=\"%s\" "),
3453 tmp_lnk_old, tmp_lnk);
3454#else
3455 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=<%s>, link_new=<%s>"),
3456 tmp_lnk_old, tmp_lnk);
3457#endif
3458 SH_FREE(tmp_lnk);
3459 SH_FREE(tmp_lnk_old);
3460 sl_strlcat(msg, tmp, SH_MSG_BUF);
3461#ifdef REPLACE_OLD
3462 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3463 {
3464 if (p->linkpath != NULL && p->linkpath != notalink)
3465 SH_FREE(p->linkpath);
3466 if (!(theFile->link_path) ||
3467 (theFile->link_path[0] == '-' && theFile->link_path[1] == '\0'))
3468 p->linkpath = (char *)notalink;
3469 else
3470 p->linkpath = sh_util_strdup(theFile->link_path);
3471 }
3472#endif
3473 }
3474
3475
3476 tmp_path = sh_util_safe_name(theFile->fullpath);
3477 sh_error_handle(log_severity, FIL__, __LINE__,
3478 (long) modi_mask, MSG_FI_CHAN,
3479 (policy_override == NULL) ? _(policy[class]):log_policy,
3480 change_code, tmp_path, msg);
3481
3482 SH_FREE(tmp_path);
3483 SH_FREE(tmp);
3484 SH_FREE(msg);
3485
3486#ifndef REPLACE_OLD
3487 SET_SH_FFLAG_REPORTED(p->fflags);
3488#endif
3489
3490 if (S_TRUE == sh.flag.update)
3491 {
3492 if (S_FALSE == sh_util_ask_update(theFile->fullpath))
3493 {
3494 /* user does not want to update, thus we replace
3495 * with data from the baseline database
3496 */
3497 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
3498 theFile->mode = p->theFile.mode;
3499#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3500 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
3501 theFile->attributes = p->theFile.attributes;
3502#endif
3503#if defined(USE_ACL) || defined(USE_XATTR)
3504 if (theFile->attr_string == NULL && p->attr_string != NULL)
3505 { theFile->attr_string = sh_util_strdup (p->attr_string); }
3506 else if (theFile->attr_string != NULL && p->attr_string == NULL)
3507 { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
3508 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3509 {
3510 if (0 != strcmp(theFile->attr_string, p->attr_string))
3511 {
3512 SH_FREE(theFile->attr_string);
3513 theFile->attr_string = sh_util_strdup (p->attr_string);
3514 }
3515 }
3516#endif
3517
3518 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
3519 {
3520 if (theFile->link_path)
3521 SH_FREE(theFile->link_path);
3522 if (p->linkpath)
3523 theFile->link_path = sh_util_strdup(p->linkpath);
3524 else
3525 theFile->link_path = sh_util_strdup("-");
3526 }
3527 else
3528 {
3529 if (theFile->link_path)
3530 SH_FREE(theFile->link_path);
3531 if (p->linkpath && p->linkpath != notalink)
3532 theFile->link_path = sh_util_strdup(p->linkpath);
3533 else
3534 theFile->link_path = NULL;
3535 }
3536
3537 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
3538
3539 theFile->mtime = p->theFile.mtime;
3540 theFile->ctime = p->theFile.ctime;
3541 theFile->atime = p->theFile.atime;
3542
3543 theFile->size = p->theFile.size;
3544
3545 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
3546 theFile->group = p->theFile.group;
3547 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
3548 theFile->owner = p->theFile.owner;
3549
3550 theFile->ino = p->theFile.ino;
3551 theFile->rdev = p->theFile.rdev;
3552 theFile->dev = p->theFile.dev;
3553 theFile->hardlinks = p->theFile.hardlinks;
3554
3555 SET_SH_FFLAG_VISITED(p->fflags);
3556 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3557 retval = 1;
3558 goto unlock_and_return;
3559 }
3560 else /* if (sh.flag.reportonce == S_TRUE) */
3561 {
3562 /* we replace the data in the in-memory copy of the
3563 * baseline database, because otherwise we would get
3564 * another warning if the suidcheck runs
3565 */
3566 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3567 p->theFile.mode = theFile->mode;
3568#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3569 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
3570 p->theFile.attributes = theFile->attributes;
3571#endif
3572#if defined(USE_ACL) || defined(USE_XATTR)
3573 if (p->attr_string == NULL && theFile->attr_string != NULL)
3574 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3575 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3576 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3577 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3578 {
3579 if (0 != strcmp(theFile->attr_string, p->attr_string))
3580 {
3581 SH_FREE(p->attr_string);
3582 p->attr_string = sh_util_strdup (theFile->attr_string);
3583 }
3584 }
3585#endif
3586
3587 if (theFile->c_mode[0] == 'l' || theFile->link_path)
3588 {
3589 if (p->linkpath != NULL && p->linkpath != notalink)
3590 SH_FREE(p->linkpath);
3591 p->linkpath = sh_util_strdup(theFile->link_path);
3592 }
3593 else
3594 {
3595 if (p->linkpath != NULL && p->linkpath != notalink) {
3596 SH_FREE(p->linkpath);
3597 }
3598 p->linkpath = (char *)notalink;
3599 }
3600
3601 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3602
3603 p->theFile.mtime = theFile->mtime;
3604 p->theFile.ctime = theFile->ctime;
3605 p->theFile.atime = theFile->atime;
3606
3607 p->theFile.size = theFile->size;
3608
3609 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3610 p->theFile.group = theFile->group;
3611 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3612 p->theFile.owner = theFile->owner;
3613
3614 p->theFile.ino = theFile->ino;
3615 p->theFile.rdev = theFile->rdev;
3616 p->theFile.dev = theFile->dev;
3617 p->theFile.hardlinks = theFile->hardlinks;
3618 }
3619 }
3620 }
3621
3622 SET_SH_FFLAG_VISITED(p->fflags);
3623 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3624
3625 unlock_and_return:
3626 ; /* 'label at end of compound statement */
3627 SH_MUTEX_UNLOCK(mutex_hash);
3628 SL_RETURN(retval, _("sh_hash_compdata"));
3629}
3630
3631int hash_full_tree ()
3632{
3633 sh_file_t * p;
3634 int i;
3635
3636 SL_ENTER(_("sh_hash_compdata"));
3637
3638 if (IsInit != 1)
3639 SL_RETURN(0, _("sh_hash_compdata"));
3640
3641 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
3642 for (i = 0; i < TABSIZE; ++i)
3643 {
3644 for (p = tab[i]; p; p = p->next)
3645 CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
3646 }
3647 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
3648 SL_RETURN (0, _("sh_hash_compdata"));
3649}
3650
3651
3652int hash_remove_tree (char * s)
3653{
3654 sh_file_t * p;
3655 size_t len;
3656 unsigned int i;
3657
3658 SL_ENTER(_("hash_remove_tree"));
3659
3660 if (!s || *s == '\0')
3661 SL_RETURN ((-1), _("hash_remove_tree"));
3662
3663 len = sl_strlen(s);
3664
3665 if (IsInit != 1)
3666 sh_hash_init();
3667
3668 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
3669 for (i = 0; i < TABSIZE; ++i)
3670 {
3671 for (p = tab[i]; p; p = p->next)
3672 {
3673 if (p->fullpath && 0 == strncmp(s, p->fullpath, len))
3674 {
3675 SET_SH_FFLAG_ALLIGNORE(p->fflags);
3676 }
3677 }
3678 }
3679 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
3680 SL_RETURN ((0), _("hash_remove_tree"));
3681}
3682
3683#if TIME_WITH_SYS_TIME
3684#include <sys/time.h>
3685#include <time.h>
3686#else
3687#if HAVE_SYS_TIME_H
3688#include <sys/time.h>
3689#else
3690#include <time.h>
3691#endif
3692#endif
3693
3694static int ListFullDetail = S_FALSE;
3695static int ListWithDelimiter = S_FALSE;
3696static char * ListFile = NULL;
3697
3698int set_list_file (const char * c)
3699{
3700 ListFile = sh_util_strdup(c);
3701 return 0;
3702}
3703
3704int set_full_detail (const char * c)
3705{
3706 (void) c;
3707 ListFullDetail = S_TRUE;
3708 return 0;
3709}
3710
3711int set_list_delimited (const char * c)
3712{
3713 (void) c;
3714 ListFullDetail = S_TRUE;
3715 ListWithDelimiter = S_TRUE;
3716 return 0;
3717}
3718
3719/* Always quote the string, except if it is empty. Quote quotes by
3720 * doubling them.
3721 */
3722char * csv_escape(const char * str)
3723{
3724 const char * p = str;
3725 const char * q;
3726
3727 size_t size = 0;
3728 size_t flag_quote = 0;
3729 int flag_comma = 0;
3730 char * new;
3731 char * pnew;
3732
3733 if (p)
3734 {
3735
3736 while (*p)
3737 {
3738 if (*p == ',')
3739 flag_comma = 1;
3740 else if (*p == '"')
3741 ++flag_quote;
3742
3743 ++size; ++p;
3744 }
3745
3746 if (sl_ok_adds(size, flag_quote))
3747 size += flag_quote; /* double each quote */
3748 else
3749 return NULL;
3750
3751 if (sl_ok_adds(size, 3))
3752 size += 3; /* two quotes and terminating null */
3753 else
3754 return NULL;
3755
3756 new = SH_ALLOC(size);
3757
3758 if (flag_quote != 0)
3759 {
3760 new[0] = '"';
3761 pnew = &new[1];
3762 q = str;
3763 while (*q)
3764 {
3765 *pnew = *q;
3766 if (*pnew == '"')
3767 {
3768 ++pnew; *pnew = '"';
3769 }
3770 ++pnew; ++q;
3771 }
3772 *pnew = '"'; ++pnew;
3773 *pnew = '\0';
3774 }
3775 else
3776 {
3777 if (size > 3)
3778 {
3779 new[0] = '"';
3780 sl_strlcpy (&new[1], str, size-1);
3781 new[size-2] = '"';
3782 new[size-1] = '\0';
3783 }
3784 else
3785 {
3786 new[0] = '\0';
3787 }
3788 }
3789
3790 return new;
3791 }
3792 return NULL;
3793}
3794
3795
3796
3797void sh_hash_list_db_entry_full_detail (sh_file_t * p)
3798{
3799 char * tmp;
3800 char * esc;
3801 char str[81];
3802
3803 if (ListWithDelimiter == S_TRUE)
3804 {
3805 printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "),
3806 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3807 p->theFile.c_mode, (int) p->theFile.mode,
3808 p->theFile.c_attributes, (int) p->theFile.attributes,
3809 (int) p->theFile.hardlinks,
3810 p->theFile.c_owner, (int) p->theFile.owner,
3811 p->theFile.c_group, (int) p->theFile.group);
3812 }
3813 else
3814 {
3815 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
3816 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3817 p->theFile.c_mode, (int) p->theFile.mode,
3818 p->theFile.c_attributes, (int) p->theFile.attributes,
3819 (int) p->theFile.hardlinks,
3820 p->theFile.c_owner, (int) p->theFile.owner,
3821 p->theFile.c_group, (int) p->theFile.group);
3822 }
3823
3824 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3825 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev);
3826 else
3827 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size);
3828
3829 printf( _(" %8s"), str);
3830 if (ListWithDelimiter == S_TRUE)
3831 putchar(',');
3832
3833 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str)));
3834 if (ListWithDelimiter == S_TRUE)
3835 putchar(',');
3836 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str)));
3837 if (ListWithDelimiter == S_TRUE)
3838 putchar(',');
3839 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str)));
3840 if (ListWithDelimiter == S_TRUE)
3841 putchar(',');
3842 printf( _(" %s"), p->theFile.checksum);
3843 if (ListWithDelimiter == S_TRUE)
3844 putchar(',');
3845
3846 tmp = sh_util_safe_name(p->fullpath);
3847 if (ListWithDelimiter != S_TRUE)
3848 {
3849 printf( _(" %s"), tmp);
3850 }
3851 else
3852 {
3853 esc = csv_escape(tmp);
3854 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3855 if (esc)
3856 SH_FREE(esc);
3857 }
3858 SH_FREE(tmp);
3859
3860 if ('l' == p->theFile.c_mode[0])
3861 {
3862 tmp = sh_util_safe_name(p->linkpath);
3863 if (ListWithDelimiter != S_TRUE)
3864 {
3865 printf(_(" -> %s"), tmp);
3866 }
3867 else
3868 {
3869 esc = csv_escape(tmp);
3870 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3871 if (esc)
3872 SH_FREE(esc);
3873 }
3874 SH_FREE(tmp);
3875 }
3876
3877 if (p->attr_string)
3878 {
3879 tmp = sh_util_safe_name(p->attr_string);
3880 if (ListWithDelimiter != S_TRUE)
3881 {
3882 printf(_(" %s"), tmp);
3883 }
3884 else
3885 {
3886 esc = csv_escape(tmp);
3887 printf( _(" %s"), (esc != NULL) ? esc : _("(null)"));
3888 if (esc)
3889 SH_FREE(esc);
3890 }
3891 SH_FREE(tmp);
3892 }
3893 else
3894 {
3895 if (ListWithDelimiter == S_TRUE)
3896 printf("%s",_(" no_attr"));
3897 }
3898 putchar('\n');
3899
3900 return;
3901}
3902
3903void sh_hash_list_db_entry (sh_file_t * p)
3904{
3905 char nowtime[128];
3906 char thetime[128];
3907 char * tmp;
3908 time_t now = time(NULL);
3909 time_t then = (time_t) p->theFile.mtime;
3910
3911#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
3912 struct tm * time_ptr;
3913 struct tm time_tm;
3914
3915 time_ptr = gmtime_r(&then, &time_tm);
3916 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
3917 time_ptr = gmtime_r(&now, &time_tm);
3918 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
3919 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3920 {
3921 time_ptr = gmtime_r(&then, &time_tm);
3922 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
3923 }
3924#else
3925 strftime(thetime, 127, _("%b %d %Y"), gmtime(&then));
3926 strftime(nowtime, 127, _("%b %d %Y"), gmtime(&now));
3927 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3928 strftime(thetime, 127, _("%b %d %H:%M"), gmtime(&then));
3929#endif
3930
3931 tmp = sh_util_safe_name(p->fullpath);
3932 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3933 printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"),
3934 p->theFile.c_mode, (int) p->theFile.hardlinks,
3935 p->theFile.c_owner, p->theFile.c_group,
3936 (int) major((dev_t)p->theFile.rdev),
3937 (int) minor((dev_t)p->theFile.rdev),
3938 thetime,
3939 tmp);
3940 else
3941 printf(_("%10s %3d %-8s %-8s %8ld %s %s"),
3942 p->theFile.c_mode, (int) p->theFile.hardlinks,
3943 p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size,
3944 thetime,
3945 tmp);
3946 SH_FREE(tmp);
3947
3948 if ('l' == p->theFile.c_mode[0])
3949 {
3950 tmp = sh_util_safe_name(p->linkpath);
3951 printf(_(" -> %s\n"), tmp);
3952 SH_FREE(tmp);
3953 }
3954 else
3955 printf("\n");
3956
3957 return;
3958}
3959
3960#ifdef HAVE_LIBZ
3961#include <zlib.h>
3962#endif
3963
3964int sh_hash_printcontent(char * linkpath)
3965{
3966#ifdef HAVE_LIBZ
3967 unsigned char * decoded;
3968 unsigned char * decompressed = NULL;
3969 size_t dlen;
3970 unsigned long clen;
3971 unsigned long clen_o;
3972 int res;
3973
3974 if (linkpath && *linkpath != '-')
3975 {
3976 dlen = sh_util_base64_dec_alloc (&decoded,
3977 (unsigned char *)linkpath,
3978 strlen(linkpath));
3979
3980 clen = dlen * 2 + 1;
3981
3982 do {
3983 if (decompressed)
3984 SH_FREE(decompressed);
3985 clen += dlen; clen_o = clen;
3986 decompressed = SH_ALLOC(clen);
3987 res = uncompress(decompressed, &clen, decoded, dlen);
3988 if (res == Z_MEM_ERROR)
3989 { fprintf(stderr, "%s",_("Error: Not enough memory\n")); return -1; }
3990 if (res == Z_DATA_ERROR)
3991 { fprintf(stderr, "%s",_("Error: Data corrupt or incomplete\n")); return -1; }
3992 } while (res == Z_BUF_ERROR || clen == clen_o);
3993
3994 decompressed[clen] = '\0';
3995 fputs( (char*) decompressed, stdout);
3996 SH_FREE(decompressed);
3997 return 0;
3998 }
3999#else
4000 (void) linkpath;
4001#endif
4002 fprintf(stderr, "%s",_("Error: No data available\n"));
4003 return -1;
4004}
4005
4006int sh_hash_list_db (const char * db_file)
4007{
4008 sh_file_t * p;
4009 SL_TICKET fd;
4010 char * line;
4011 int flag = 0;
4012
4013 if (!db_file)
4014 {
4015 _exit(EXIT_FAILURE);
4016 return -1;
4017 }
4018 if (sl_is_suid())
4019 {
4020 fprintf(stderr, "%s",_("ERROR: insufficient privilege\n"));
4021 _exit (EXIT_FAILURE);
4022 return -1; /* for Mac OSX compiler */
4023 }
4024 if (0 == strcmp(db_file, _("default")))
4025 db_file = file_path('D', 'W');
4026 if (!db_file)
4027 {
4028 _exit(EXIT_FAILURE);
4029 return -1;
4030 }
4031
4032 line = SH_ALLOC(MAX_PATH_STORE+2);
4033
4034 if ( SL_ISERROR(fd = sl_open_read(db_file, SL_YESPRIV)))
4035 {
4036 fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"),
4037 db_file, fd);
4038 _exit(EXIT_FAILURE);
4039 return -1;
4040 }
4041
4042 /* fast forward to start of data
4043 */
4044 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, db_file);
4045
4046 while (1)
4047 {
4048 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
4049 if ((p != NULL) && (p->fullpath[0] == '/'))
4050 {
4051 if (!ListFile)
4052 {
4053 flag = 1;
4054 if (ListFullDetail == S_FALSE)
4055 sh_hash_list_db_entry (p);
4056 else
4057 sh_hash_list_db_entry_full_detail (p);
4058 }
4059 else
4060 {
4061 if (0 != sl_strcmp(ListFile, p->fullpath))
4062 {
4063 continue;
4064 }
4065 flag = 1;
4066 if ('l' != p->theFile.c_mode[0])
4067 {
4068 if (sh_hash_printcontent(p->linkpath) < 0)
4069 {
4070 _exit(EXIT_FAILURE);
4071 return -1;
4072 }
4073 }
4074 else
4075 {
4076 fprintf(stderr, "%s",_("File is a link\n"));
4077 _exit(EXIT_FAILURE);
4078 return -1;
4079 }
4080 break;
4081 }
4082 }
4083 else if (p == NULL)
4084 {
4085 break;
4086 }
4087 }
4088
4089 if (line != NULL)
4090 SH_FREE(line);
4091 sl_close (fd);
4092
4093 fflush(NULL);
4094
4095 if (flag == 0)
4096 {
4097 fprintf(stderr, "%s",_("File not found\n"));
4098 _exit(EXIT_FAILURE);
4099 }
4100 _exit(EXIT_SUCCESS);
4101 return 0;
4102}
4103
4104/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
4105#endif
Note: See TracBrowser for help on using the repository browser.