source: trunk/src/sh_hash.c @ 133

Last change on this file since 133 was 133, checked in by rainer, 12 years ago

Reentrant checksum/hash functions.

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