source: trunk/src/sh_hash.c@ 356

Last change on this file since 356 was 356, checked in by katerina, 13 years ago

Patch for ticket #261: show policy for checked files in verbose mode.

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