source: trunk/src/sh_hash.c@ 481

Last change on this file since 481 was 481, checked in by katerina, 9 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

File size: 78.0 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#include <stdlib.h>
23#include <string.h>
24#include <stdio.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <unistd.h>
[444]28#include <ctype.h>
[1]29
30#ifdef MAJOR_IN_MKDEV
31#include <sys/mkdev.h>
32#else
33#ifdef MAJOR_IN_SYSMACROS
34#include <sys/sysmacros.h>
35#endif
36#endif
37
38#ifdef HAVE_MEMORY_H
39#include <memory.h>
40#endif
41
[481]42
[1]43#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
44
[481]45#include "samhain.h"
46#include "sh_utils.h"
47#include "sh_unix.h"
48#include "sh_dbIO_int.h"
49#include "sh_dbIO.h"
[1]50#include "sh_hash.h"
51#include "sh_error.h"
52#include "sh_tiger.h"
53#include "sh_gpg.h"
54#include "sh_unix.h"
55#include "sh_files.h"
56#include "sh_ignore.h"
[149]57#include "sh_pthread.h"
[1]58
59#if defined(SH_WITH_CLIENT)
[481]60#include "sh_xfer.h"
[1]61#endif
62
[105]63
64#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
65
66
[1]67#undef FIL__
68#define FIL__ _("sh_hash.c")
69
[481]70SH_MUTEX_INIT(mutex_hash,PTHREAD_MUTEX_INITIALIZER);
[149]71
[1]72static char * all_items (file_type * theFile, char * fileHash, int is_new);
73
[481]74static const char *policy[] = {
75 N_("[]"),
76 N_("[ReadOnly]"),
77 N_("[LogFiles]"),
78 N_("[GrowingLogs]"),
79 N_("[IgnoreNone]"),
80 N_("[IgnoreAll]"),
81 N_("[Attributes]"),
82 N_("[User0]"),
83 N_("[User1]"),
84 N_("[User2]"),
85 N_("[User3]"),
86 N_("[User4]"),
87 N_("[Prelink]"),
88 NULL
89};
[1]90
[481]91static int report_checkflags = S_FALSE;
92int set_report_checkflags(const char * c)
[1]93{
[481]94 return sh_util_flagval(c, &report_checkflags);
[1]95}
[481]96int get_report_checkflags()
[1]97{
[481]98 return report_checkflags;
[1]99}
100
[34]101
[1]102
[356]103const char * sh_hash_getpolicy(int class)
104{
105 if (class > 0 && class < SH_ERR_T_DIR)
106 return _(policy[class]);
107 return _("[indef]");
108}
[1]109
110/**********************************
111 *
112 * hash table functions
113 *
114 **********************************
115 */
116
117#include "sh_hash.h"
118
119
120/**************************************************************
121 *
122 * create a file_type from a sh_file_t
123 *
124 **************************************************************/
[481]125file_type * sh_hash_create_ft (const sh_file_t * p, char * fileHash)
[1]126{
127 file_type * theFile;
128
129 SL_ENTER(_("sh_hash_create_ft"));
130
131 theFile = SH_ALLOC(sizeof(file_type));
132
133 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
134 theFile->mode = p->theFile.mode;
[10]135#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[149]136 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, ATTRBUF_SIZE);
[1]137 theFile->attributes = p->theFile.attributes;
138#endif
139
140 sl_strlcpy(theFile->fullpath, p->fullpath, PATH_MAX);
[167]141 if (p->linkpath != NULL /* && theFile->c_mode[0] == 'l' */)
[1]142 {
[167]143 theFile->link_path = sh_util_strdup(p->linkpath);
[1]144 }
145 else
146 {
[167]147 theFile->link_path = NULL;
[1]148 }
149 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
150
151 theFile->mtime = p->theFile.mtime;
152 theFile->ctime = p->theFile.ctime;
153 theFile->atime = p->theFile.atime;
154
155 theFile->size = p->theFile.size;
156
157 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
158 theFile->group = p->theFile.group;
159 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
160 theFile->owner = p->theFile.owner;
161
162 theFile->ino = p->theFile.ino;
163 theFile->rdev = p->theFile.rdev;
164 theFile->dev = p->theFile.dev;
165 theFile->hardlinks = p->theFile.hardlinks;
[481]166 theFile->check_flags = p->theFile.checkflags;
[1]167
[68]168 if (p->attr_string)
169 theFile->attr_string = sh_util_strdup(p->attr_string);
170 else
171 theFile->attr_string = NULL;
172
[1]173 SL_RETURN((theFile), _("sh_hash_create_ft"));
174}
175
[305]176struct two_sh_file_t {
177 sh_file_t * prev;
178 sh_file_t * this;
179};
180
[294]181static sh_file_t * hashsearch (const char * s);
[305]182static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index);
[1]183
[481]184
185/**************************************************************
186 *
187 * >>>> The internal database <<<
188 *
189 **************************************************************/
190
[1]191static sh_file_t * tab[TABSIZE];
192
[481]193sh_file_t ** get_default_data_table()
194{
195 return tab;
196}
197
[1]198/**************************************************************
199 *
200 * compute hash function
201 *
202 **************************************************************/
[8]203
[294]204static int hashfunc(const char *s)
[1]205{
[18]206 unsigned int n = 0;
[1]207
208 for ( ; *s; s++)
209 n = 31 * n + *s;
[18]210
211 return n & (TABSIZE - 1); /* % TABSIZE */;
[1]212}
213
[8]214
[1]215int hashreport_missing( char *fullpath, int level)
216{
217 sh_file_t * p;
218 char * tmp;
219 char fileHash[KEY_LEN + 1];
220 file_type * theFile;
221 char * str;
[133]222 char hashbuf[KEYBUF_SIZE];
[367]223 volatile int retval;
[1]224
225 /* -------- find the entry for the file ---------------- */
226
[149]227 SH_MUTEX_LOCK(mutex_hash);
228
[170]229 retval = 0;
230
[1]231 if (sl_strlen(fullpath) <= MAX_PATH_STORE)
232 p = hashsearch(fullpath);
233 else
234 p = hashsearch( sh_tiger_hash(fullpath,
235 TIGER_DATA,
[133]236 sl_strlen(fullpath),
237 hashbuf, sizeof(hashbuf))
[1]238 );
239 if (p == NULL)
[149]240 {
241 retval = -1;
242 goto unlock_and_return;
243 }
[1]244
245 theFile = sh_hash_create_ft (p, fileHash);
246 str = all_items(theFile, fileHash, 0);
247 tmp = sh_util_safe_name(fullpath);
[367]248
249 SH_MUTEX_LOCK(mutex_thread_nolog);
[1]250 sh_error_handle (level, FIL__, __LINE__, 0,
251 MSG_FI_MISS2, tmp, str);
[367]252 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[405]253 ++sh.statistics.files_report;
[362]254
[1]255 SH_FREE(tmp);
256 SH_FREE(str);
[167]257 if (theFile->attr_string) SH_FREE(theFile->attr_string);
258 if (theFile->link_path) SH_FREE(theFile->link_path);
[1]259 SH_FREE(theFile);
[149]260
261 unlock_and_return:
[153]262 ; /* 'label at end of compound statement */
[149]263 SH_MUTEX_UNLOCK(mutex_hash);
[305]264
[458]265 /* remove here to avoid second message from hash_unvisited */
266 if (retval == 0)
267 sh_hash_remove (fullpath);
268
[149]269 return retval;
[1]270}
271
272
273/**************************************************************
274 *
275 * search for files not visited, and check whether they exist
276 *
277 **************************************************************/
[294]278static sh_file_t * delete_db_entry(sh_file_t *p)
279{
280 if (p->fullpath)
281 {
282 SH_FREE(p->fullpath);
283 p->fullpath = NULL;
284 }
285 if (p->linkpath)
286 {
[481]287 SH_FREE(p->linkpath);
[294]288 p->linkpath = NULL;
289 }
290 if (p->attr_string)
291 {
292 SH_FREE(p->attr_string);
293 p->attr_string = NULL;
294 }
295 SH_FREE(p);
296 return NULL;
297}
298
[1]299static void hash_unvisited (int j,
300 sh_file_t *prev, sh_file_t *p, ShErrLevel level)
301{
302 struct stat buf;
303 int i;
304 char * tmp;
305 char * ptr;
306 char fileHash[KEY_LEN + 1];
307 file_type * theFile;
308 char * str;
309
310 SL_ENTER(_("hash_unvisited"));
311
312 if (p->next != NULL)
313 hash_unvisited (j, p, p->next, level);
314
315 if (p->fullpath == NULL)
316 {
317 SL_RET0(_("hash_unvisited"));
318 }
319
[114]320 /* Not a fully qualified path, i.e. some info stored by some module
[1]321 */
[114]322 if (p->fullpath[0] != '/')
[1]323 {
324 SL_RET0(_("hash_unvisited"));
325 }
[458]326
[114]327 /* visited flag not set: not seen;
328 * checked flag set: not seen (i.e. missing), and already checked
329 * reported flag not set: not reported yet
330 * allignore flag not set: not under IgnoreAll
[1]331 *
332 * Files/directories under IgnoreAll are noticed as missing already
333 * during the file check.
334 */
[114]335 if (((!SH_FFLAG_VISITED_SET(p->fflags)) || SH_FFLAG_CHECKED_SET(p->fflags))
336 && (!SH_FFLAG_REPORTED_SET(p->fflags))
[481]337 /* && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)) */)
[1]338 {
339 i = retry_lstat(FIL__, __LINE__, p->fullpath, &buf);
[458]340
[457]341 /* if file does not exist
[1]342 */
343 if (0 != i)
344 {
[34]345 ptr = sh_util_dirname (p->fullpath);
[1]346 if (ptr)
347 {
348 /* If any of the parent directories is under IgnoreAll
349 */
[481]350 if ((0 != sh_files_is_allignore(ptr)) || SH_FFLAG_ALLIGNORE_SET(p->fflags))
[1]351 level = ShDFLevel[SH_LEVEL_ALLIGNORE];
352 SH_FREE(ptr);
353 }
[114]354
355 /* Only report if !SH_FFLAG_CHECKED_SET
356 */
357 if (!SH_FFLAG_CHECKED_SET(p->fflags))
[1]358 {
359 if (S_FALSE == sh_ignore_chk_del(p->fullpath))
360 {
361 tmp = sh_util_safe_name(p->fullpath);
362
363 theFile = sh_hash_create_ft (p, fileHash);
364 str = all_items(theFile, fileHash, 0);
365 sh_error_handle (level, FIL__, __LINE__, 0,
366 MSG_FI_MISS2, tmp, str);
[405]367 ++sh.statistics.files_report;
[1]368 SH_FREE(str);
[167]369 if (theFile->attr_string) SH_FREE(theFile->attr_string);
370 if (theFile->link_path) SH_FREE(theFile->link_path);
[1]371 SH_FREE(theFile);
372
373 SH_FREE(tmp);
374 }
375 }
376
[77]377 /* We rewrite the db on update, thus we need to keep this
[1]378 * if the user does not want to purge it from the db.
379 */
380
[77]381 if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) ||
382 (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(p->fullpath)))
[1]383 {
384 /* Remove the old entry
385 */
386 if (prev == p)
387 tab[j] = p->next;
388 else
389 prev->next = p->next;
[294]390
[383]391 delete_db_entry(p);
[294]392
[1]393 SL_RET0(_("hash_unvisited"));
394 }
395 }
396 }
397
[114]398 else if (SH_FFLAG_VISITED_SET(p->fflags) && SH_FFLAG_REPORTED_SET(p->fflags)
399 && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)))
[1]400 {
401 if (S_FALSE == sh_ignore_chk_new(p->fullpath))
402 {
403 tmp = sh_util_safe_name(p->fullpath);
404
405 theFile = sh_hash_create_ft (p, fileHash);
406 str = all_items(theFile, fileHash, 0);
407 sh_error_handle (level, FIL__, __LINE__, 0,
408 MSG_FI_MISS2, tmp, str);
[405]409 ++sh.statistics.files_report;
[1]410 SH_FREE(str);
[68]411 if (theFile->attr_string)
412 SH_FREE(theFile->attr_string);
[1]413 SH_FREE(theFile);
414
415 SH_FREE(tmp);
416 }
417
[114]418 CLEAR_SH_FFLAG_REPORTED(p->fflags);
[1]419 }
420
421 if (sh.flag.reportonce == S_FALSE)
[114]422 CLEAR_SH_FFLAG_REPORTED(p->fflags);
[1]423
[114]424 CLEAR_SH_FFLAG_VISITED(p->fflags);
425 CLEAR_SH_FFLAG_CHECKED(p->fflags);
[458]426 SET_SH_FFLAG_ENOENT(p->fflags);
[114]427
[1]428 SL_RET0(_("hash_unvisited"));
429}
430
431
[305]432
[1]433/*********************************************************************
434 *
435 * Search for files in the database that have been deleted from disk.
436 *
437 *********************************************************************/
438void sh_hash_unvisited (ShErrLevel level)
439{
440 int i;
441
442 SL_ENTER(_("sh_hash_unvisited"));
[149]443
444 SH_MUTEX_LOCK(mutex_hash);
[1]445 for (i = 0; i < TABSIZE; ++i)
446 {
447 if (tab[i] != NULL)
448 hash_unvisited (i, tab[i], tab[i], level);
449 }
[149]450 SH_MUTEX_UNLOCK(mutex_hash);
451
[1]452 SL_RET0(_("hash_unvisited"));
453}
454
[294]455/*********************************************************************
456 *
[305]457 * Remove a single file from the database.
458 *
459 *********************************************************************/
[481]460void sh_hash_remove_unconditional (const char * path)
[305]461{
462 struct two_sh_file_t entries;
463 int index;
464
[481]465 SL_ENTER(_("sh_hash_remove_unconditional"));
[305]466
467 SH_MUTEX_LOCK(mutex_hash);
[481]468 if (0 == hashsearch_prev (path, &entries, &index))
469 {
470 sh_file_t * p = entries.this;
471
472 /* Remove the old entry
473 */
474 if (entries.prev == p)
475 tab[index] = p->next;
476 else
477 entries.prev->next = p->next;
478
479 delete_db_entry(p);
480 }
481 SH_MUTEX_UNLOCK(mutex_hash);
[305]482
[481]483 SL_RET0(_("sh_hash_remove_unconditional"));
484}
485
486void sh_hash_remove (const char * path)
487{
488 SL_ENTER(_("sh_hash_remove"));
489
[305]490 if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) ||
491 (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(path)))
492 {
[481]493 sh_hash_remove_unconditional (path);
[305]494 }
495 SL_RET0(_("sh_hash_remove"));
496}
497
498
499/*********************************************************************
500 *
[294]501 * Search for unvisited entries in the database, custom error handler.
502 *
503 *********************************************************************/
504void sh_hash_unvisited_custom (char prefix, void(*handler)(const char * key))
505{
506 int i;
507 sh_file_t *p = NULL;
508 sh_file_t *prev = NULL;
509 sh_file_t *next = NULL;
[1]510
[294]511 SL_ENTER(_("sh_hash_unvisited_custom"));
512
513 SH_MUTEX_LOCK(mutex_hash);
514 for (i = 0; i < TABSIZE; ++i)
515 {
516 if (tab[i] != NULL)
517 {
518 p = tab[i]; prev = p;
519
520 do
521 {
522 next = p->next;
523
524 if (p->fullpath &&
525 prefix == p->fullpath[0])
526 {
527 if ((!SH_FFLAG_VISITED_SET(p->fflags))
528 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
529 {
530 handler(p->fullpath);
531
532 if (!SH_FFLAG_CHECKED_SET(p->fflags))
533 {
534 /* delete */
535 if (tab[i] == p)
536 {
537 tab[i] = p->next;
538 prev = tab[i];
539 next = prev;
540 }
541 else
542 {
543 prev->next = p->next;
544 next = prev->next;
545 }
546
547 p = delete_db_entry(p);
548 }
549 }
550 if (p)
551 {
552 CLEAR_SH_FFLAG_VISITED(p->fflags);
553 CLEAR_SH_FFLAG_CHECKED(p->fflags);
554 }
555 }
556 if (p)
557 prev = p;
558 p = next;
559 }
560 while (p);
561 }
562 }
563 SH_MUTEX_UNLOCK(mutex_hash);
564
565 SL_RET0(_("hash_unvisited_custom"));
566}
567
568
[1]569/**********************************************************************
570 *
571 * delete hash array
572 *
573 **********************************************************************/
574static void hash_kill (sh_file_t *p)
575{
576 SL_ENTER(_("hash_kill"));
577
578 if (p == NULL)
579 SL_RET0(_("hash_kill"));
580
581 if (p->next != NULL)
582 hash_kill (p->next);
583
584 if (p->fullpath)
585 {
586 SH_FREE(p->fullpath);
587 p->fullpath = NULL;
588 }
589 if (p->linkpath)
590 {
[481]591 SH_FREE(p->linkpath);
[1]592 p->linkpath = NULL;
593 }
[68]594 if (p->attr_string)
595 {
596 SH_FREE(p->attr_string);
597 p->attr_string = NULL;
598 }
[1]599 SH_FREE(p);
600 p = NULL;
601 SL_RET0(_("hash_kill"));
602}
603
604
605/***********************************************************************
606 *
607 * get info out of hash array
608 *
609 ***********************************************************************/
[294]610static sh_file_t * hashsearch (const char * s)
[1]611{
612 sh_file_t * p;
613
614 SL_ENTER(_("hashsearch"));
615
[8]616 if (s)
617 {
618 for (p = tab[hashfunc(s)]; p; p = p->next)
619 if ((p->fullpath != NULL) && (0 == strcmp(s, p->fullpath)))
620 SL_RETURN( p, _("hashsearch"));
621 }
[1]622 SL_RETURN( NULL, _("hashsearch"));
623}
624
[305]625static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index)
626{
627 sh_file_t * this;
628 sh_file_t * prev = NULL;
[1]629
[305]630 SL_ENTER(_("hashsearch_prev"));
631
632 if (s)
633 {
634 *index = hashfunc(s);
[481]635 this = tab[*index];
636 prev = this;
[305]637
638 if (this)
639 {
640 do {
641 if ((this->fullpath != NULL) && (0 == strcmp(s, this->fullpath)))
642 {
643 a->prev = prev;
[481]644 a->this = this;
[305]645 SL_RETURN( 0, _("hashsearch_prev"));
646 }
647 prev = this;
648 this = this->next;
649 } while(this);
650 }
651 }
652 SL_RETURN( -1, _("hashsearch"));
653}
654
655
[1]656/***********************************************************************
657 *
658 * insert into hash array
659 *
660 ***********************************************************************/
[481]661void hashinsert (sh_file_t * mtab[TABSIZE], sh_file_t * s)
[1]662{
663 sh_file_t * p;
[3]664 sh_file_t * q;
[1]665 int key;
666
667 SL_ENTER(_("hashinsert"));
668
669 key = hashfunc(s->fullpath);
670
[481]671 if (mtab[key] == NULL)
[1]672 {
[481]673 mtab[key] = s;
674 mtab[key]->next = NULL;
[1]675 SL_RET0(_("hashinsert"));
676 }
677 else
678 {
[481]679 p = mtab[key];
[1]680 while (1)
681 {
[481]682 if (p && p->fullpath && 0 == strcmp(s->fullpath, p->fullpath))
[1]683 {
[3]684 q = p->next;
685 SH_FREE(p->fullpath);
[481]686 if(p->linkpath) SH_FREE(p->linkpath);
687 if(p->attr_string) SH_FREE(p->attr_string);
[3]688 memcpy(p, s, sizeof(sh_file_t));
689 p->next = q;
[481]690 SH_FREE(s); s = NULL;
[1]691 SL_RET0(_("hashinsert"));
692 }
[383]693 else if (p && p->next == NULL)
694 {
695 p->next = s;
696 p->next->next = NULL;
697 SL_RET0(_("hashinsert"));
698 }
699 if (p)
700 p = p->next;
701 else /* cannot really happen, but llvm/clang does not know */
702 break;
[1]703 }
704 }
705 /* notreached */
706}
707
708
709
710/******************************************************************
711 *
712 * ------- Check functions -------
713 *
714 ******************************************************************/
715
716static int IsInit = 0;
717
[481]718void sh_hash_set_initialized()
[1]719{
[481]720 IsInit = 1;
721 return;
[1]722}
723
[481]724int sh_hash_get_initialized()
[1]725{
[481]726 return IsInit;
[1]727}
728
729
730/******************************************************************
731 *
732 * Initialize
733 *
734 ******************************************************************/
735void sh_hash_init ()
736{
[199]737 volatile int retval = 0;
738 volatile int exitval = EXIT_SUCCESS;
[185]739
[1]740 SL_ENTER(_("sh_hash_init"));
741
[463]742 if ( sh.flag.checkSum == SH_CHECK_INIT )
743 {
744 dlog(1, FIL__, __LINE__,
745 _("Attempt to load the baseline database during initialisation. This is an internal error, please report it to the developer.\n"));
746 SH_ABORT;
747 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
748 }
749
[149]750 SH_MUTEX_LOCK(mutex_hash);
[1]751
[149]752 if (IsInit == 1)
753 {
754 goto unlock_and_return;
755 }
[1]756
[149]757 /* Initialization completed.
758 */
[481]759 retval = sh_dbIO_load_db(tab);
[149]760
[481]761 if (0 == retval)
762 IsInit = 1;
763 else
764 exitval = EXIT_FAILURE;
[1]765
[149]766 unlock_and_return:
[153]767 ; /* 'label at end of compound statement */
[149]768 SH_MUTEX_UNLOCK(mutex_hash);
[185]769 if (retval == 0)
770 {
771 SL_RET0(_("sh_hash_init"));
772 }
[481]773 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name);
[185]774 aud_exit (FIL__, __LINE__, exitval);
[1]775}
[481]776
777void sh_hash_init_and_checksum()
778{
779 TPT((0, FIL__, __LINE__, _("msg=<Get checksum of the database.>\n")))
780 if (sh.flag.checkSum == SH_CHECK_CHECK)
781 {
782 if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
783 {
784 char hashbuf[KEYBUF_SIZE];
785 (void) sl_strlcpy(sh.data.hash,
786 sh_tiger_hash (file_path('D', 'R'),
787 TIGER_FILE, TIGER_NOLIM,
788 hashbuf, sizeof(hashbuf)),
789 KEY_LEN+1);
790 }
791
792 /* this eventually fetches the file from server to get checksum
793 */
794 sh_hash_init ();
795 }
796 return;
797}
[1]798
799/*****************************************************************
800 *
801 * delete hash array
802 *
803 *****************************************************************/
804void sh_hash_hashdelete ()
805{
806 int i;
807
808 SL_ENTER(_("sh_hash_hashdelete"));
809
[320]810 /* need deadlock detection here if called from exit handler
811 */
812 SH_MUTEX_TRYLOCK(mutex_hash);
813
[1]814 if (IsInit == 0)
[149]815 goto unlock_and_exit;
816
[1]817 for (i = 0; i < TABSIZE; ++i)
818 if (tab[i] != NULL)
819 {
820 hash_kill (tab[i]);
821 tab[i] = NULL;
822 }
823 IsInit = 0;
[149]824
825 unlock_and_exit:
[153]826 ; /* 'label at end of compound statement */
[371]827 SH_MUTEX_TRYLOCK_UNLOCK(mutex_hash);
[320]828
[1]829 SL_RET0(_("sh_hash_hashdelete"));
830}
831
[205]832static int sh_loosedircheck = S_FALSE;
[1]833
[205]834int sh_hash_loosedircheck(const char * str)
835{
836 return sh_util_flagval(str, &sh_loosedircheck);
837}
838
839
[1]840
841
842/*********************************************************************
843 *
844 * Check whether a file is present in the database.
845 *
846 *********************************************************************/
[294]847static sh_file_t * sh_hash_have_it_int (const char * newname)
[1]848{
849 sh_file_t * p;
[133]850 char hashbuf[KEYBUF_SIZE];
[1]851
[115]852 SL_ENTER(_("sh_hash_have_it_int"));
[1]853
854 if (newname == NULL)
[115]855 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
[1]856
857 if (sl_strlen(newname) <= MAX_PATH_STORE)
858 p = hashsearch(newname);
859 else
[133]860 p = hashsearch ( sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
861 hashbuf, sizeof(hashbuf)) );
[1]862 if (p == NULL)
[115]863 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
[149]864
[115]865 SL_RETURN( (p), _("sh_hash_have_it_int"));
[1]866}
867
[294]868int sh_hash_have_it (const char * newname)
[1]869{
[149]870 sh_file_t * p;
[170]871 int retval;
[1]872
[149]873 if (IsInit != 1)
874 sh_hash_init();
875
876 SH_MUTEX_LOCK(mutex_hash);
[170]877
878 retval = 0;
879
[149]880 p = sh_hash_have_it_int (newname);
881
882 if (!p)
883 retval = (-1);
884 else if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) &&
885 (p->modi_mask & MODI_CHK) != 0 &&
886 (p->modi_mask & MODI_MOD) != 0)
887 retval = 1;
888 SH_MUTEX_UNLOCK(mutex_hash);
889
890 return retval;
[1]891}
892
[294]893int sh_hash_get_it (const char * newname, file_type * tmpFile, char * fileHash)
[1]894{
[149]895 sh_file_t * p;
[170]896 int retval;
[68]897
[149]898 if (IsInit != 1)
899 sh_hash_init();
900
[167]901 tmpFile->link_path = NULL;
902 tmpFile->attr_string = NULL;
903
[149]904 SH_MUTEX_LOCK(mutex_hash);
[170]905
906 retval = (-1);
907
[149]908 p = sh_hash_have_it_int (newname);
909 if (p)
910 {
[167]911 sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
912 if (p->linkpath)
913 tmpFile->link_path = sh_util_strdup (p->linkpath);
[149]914 tmpFile->size = p->theFile.size;
915 tmpFile->mtime = p->theFile.mtime;
916 tmpFile->ctime = p->theFile.ctime;
[294]917 tmpFile->atime = p->theFile.atime;
918
919 if (NULL != fileHash)
920 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
921
[149]922 tmpFile->attr_string = NULL;
923 retval = 0;
924 }
925 SH_MUTEX_UNLOCK(mutex_hash);
926
927 return retval;
[1]928}
929
[115]930int sh_hash_getflags (char * filename)
931{
[149]932 sh_file_t * p;
[463]933 int retval = 0;
[149]934
[463]935 if ( sh.flag.checkSum != SH_CHECK_INIT )
936 {
937 if (IsInit != 1)
938 sh_hash_init();
939
940 SH_MUTEX_LOCK(mutex_hash);
941 p = sh_hash_have_it_int (filename);
942 if (p)
943 retval = p->fflags;
944 else
945 retval = -1;
946 SH_MUTEX_UNLOCK(mutex_hash);
947 }
[149]948 return retval;
[115]949}
950
951int sh_hash_setflags (char * filename, int flags)
952{
[149]953 sh_file_t * p;
[463]954 int retval = 0;
[149]955
[463]956 if ( sh.flag.checkSum != SH_CHECK_INIT )
[149]957 {
[463]958 if (IsInit != 1)
959 sh_hash_init();
960
961 SH_MUTEX_LOCK(mutex_hash);
962 p = sh_hash_have_it_int (filename);
963 if (p)
964 {
965 p->fflags = flags;
966 retval = 0;
967 }
968 else
969 retval = -1;
970 SH_MUTEX_UNLOCK(mutex_hash);
[149]971 }
972 return retval;
[115]973}
974
975/* needs lock to be threadsafe
976 */
[458]977void sh_hash_set_flag (char * filename, int flag_to_set)
[115]978{
[149]979 sh_file_t * p;
[115]980
[463]981 if ( sh.flag.checkSum != SH_CHECK_INIT )
[115]982 {
[463]983 if (IsInit != 1)
984 sh_hash_init();
985
986 SH_MUTEX_LOCK(mutex_hash);
987 p = sh_hash_have_it_int (filename);
988 if (p)
989 {
990 p->fflags |= flag_to_set;
991 }
992 SH_MUTEX_UNLOCK(mutex_hash);
[115]993 }
994 return;
995}
996
[458]997/* needs lock to be threadsafe
998 */
999void sh_hash_clear_flag (char * filename, int flag_to_clear)
1000{
1001 sh_file_t * p;
1002
[463]1003 if ( sh.flag.checkSum != SH_CHECK_INIT )
[458]1004 {
[463]1005 if (IsInit != 1)
1006 sh_hash_init();
1007
1008 SH_MUTEX_LOCK(mutex_hash);
1009 p = sh_hash_have_it_int (filename);
1010 if (p)
1011 {
1012 p->fflags &= ~flag_to_clear;
1013 }
1014 SH_MUTEX_UNLOCK(mutex_hash);
[458]1015 }
1016 return;
1017}
1018
1019
[1]1020/*****************************************************************
1021 *
1022 * Set a file's status to 'visited'. This is required for
1023 * files that should be ignored, and may be present in the
1024 * database, but not on disk.
1025 *
1026 *****************************************************************/
1027static int sh_hash_set_visited_int (char * newname, int flag)
1028{
1029 sh_file_t * p;
[133]1030 char hashbuf[KEYBUF_SIZE];
[170]1031 int retval;
[1]1032
1033 SL_ENTER(_("sh_hash_set_visited_int"));
1034
1035 if (newname == NULL)
1036 SL_RETURN((-1), _("sh_hash_set_visited_int"));
[149]1037
[1]1038 if (IsInit != 1)
1039 sh_hash_init();
1040
[149]1041 SH_MUTEX_LOCK(mutex_hash);
1042
[1]1043 if (sl_strlen(newname) <= MAX_PATH_STORE)
1044 p = hashsearch(newname);
1045 else
[133]1046 p = hashsearch (sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
1047 hashbuf, sizeof(hashbuf)));
[1]1048
[149]1049 if (p)
[1]1050 {
[149]1051 if (flag == SH_FFLAG_CHECKED)
1052 {
1053 CLEAR_SH_FFLAG_REPORTED(p->fflags);
1054 CLEAR_SH_FFLAG_VISITED(p->fflags);
1055 SET_SH_FFLAG_CHECKED(p->fflags);
1056 }
[114]1057 else
[149]1058 {
1059 SET_SH_FFLAG_VISITED(p->fflags);
1060 CLEAR_SH_FFLAG_CHECKED(p->fflags);
1061 if (flag == SH_FFLAG_REPORTED)
1062 SET_SH_FFLAG_REPORTED(p->fflags);
1063 else
1064 CLEAR_SH_FFLAG_REPORTED(p->fflags);
1065 }
1066 retval = 0;
[1]1067 }
[170]1068 else
1069 retval = -1;
[149]1070
1071 SH_MUTEX_UNLOCK(mutex_hash);
1072 SL_RETURN((retval), _("sh_hash_set_visited_int"));
[1]1073}
1074
1075
1076/* cause the record to be deleted without a 'missing' message
1077 */
1078int sh_hash_set_missing (char * newname)
1079{
1080 int i;
[294]1081 SL_ENTER(_("sh_hash_set_missing"));
[305]1082
[114]1083 i = sh_hash_set_visited_int(newname, SH_FFLAG_CHECKED);
[305]1084
1085 if (sh.flag.checkSum != SH_CHECK_INIT) {
1086 sh_hash_remove(newname);
1087 }
1088
[294]1089 SL_RETURN(i, _("sh_hash_set_missing"));
[1]1090}
1091
[114]1092/* mark the file as visited and reported
1093 */
[1]1094int sh_hash_set_visited (char * newname)
1095{
1096 int i;
1097 SL_ENTER(_("sh_hash_set_visited"));
[114]1098 i = sh_hash_set_visited_int(newname, SH_FFLAG_REPORTED);
[1]1099 SL_RETURN(i, _("sh_hash_set_visited"));
1100}
1101
[114]1102/* mark the file as visited and NOT reported
1103 * used to avoid deletion of file from internal database
1104 */
[1]1105int sh_hash_set_visited_true (char * newname)
1106{
1107 int i;
1108 SL_ENTER(_("sh_hash_set_visited_true"));
[114]1109 i = sh_hash_set_visited_int(newname, 0);
[1]1110 SL_RETURN(i, _("sh_hash_set_visited_true"));
1111}
1112
1113
1114/******************************************************************
1115 *
1116 * Data entry for arbitrary data into database
1117 *
1118 ******************************************************************/
1119
[294]1120void sh_hash_push2db (const char * key, struct store2db * save)
[1]1121{
1122 int i = 0;
1123 char * p;
[137]1124 char i2h[2];
[227]1125 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
[1]1126
[294]1127 int size = save->size;
1128 unsigned char * str = save->str;
1129
1130
[227]1131 tmpFile->attr_string = NULL;
1132 tmpFile->link_path = NULL;
[68]1133
[227]1134 sl_strlcpy(tmpFile->fullpath, key, PATH_MAX);
[294]1135 tmpFile->size = save->val0;
1136 tmpFile->mtime = save->val1;
1137 tmpFile->ctime = save->val2;
1138 tmpFile->atime = save->val3;
[1]1139
[227]1140 tmpFile->mode = 0;
1141 tmpFile->owner = 0;
1142 tmpFile->group = 0;
1143 sl_strlcpy(tmpFile->c_owner, _("root"), 5);
1144 sl_strlcpy(tmpFile->c_group, _("root"), 5);
[1]1145
[481]1146 tmpFile->check_flags = 0;
1147
[1]1148 if ((str != NULL) && (size < (PATH_MAX/2)-1))
1149 {
[227]1150 tmpFile->c_mode[0] = 'l';
1151 tmpFile->c_mode[1] = 'r'; tmpFile->c_mode[2] = 'w';
1152 tmpFile->c_mode[3] = 'x'; tmpFile->c_mode[4] = 'r';
1153 tmpFile->c_mode[5] = 'w'; tmpFile->c_mode[6] = 'x';
1154 tmpFile->c_mode[7] = 'r'; tmpFile->c_mode[8] = 'w';
1155 tmpFile->c_mode[9] = 'x'; tmpFile->c_mode[10] = '\0';
1156 tmpFile->link_path = SH_ALLOC((size * 2) + 2);
[1]1157 for (i = 0; i < size; ++i)
1158 {
[137]1159 p = sh_util_charhex (str[i],i2h);
[227]1160 tmpFile->link_path[2*i] = p[0];
1161 tmpFile->link_path[2*i+1] = p[1];
1162 tmpFile->link_path[2*i+2] = '\0';
[1]1163 }
1164 }
1165 else
1166 {
[93]1167 for (i = 0; i < 10; ++i)
[227]1168 tmpFile->c_mode[i] = '-';
1169 tmpFile->c_mode[10] = '\0';
1170 tmpFile->link_path = sh_util_strdup("-");
[1]1171 }
1172
[294]1173 if (sh.flag.checkSum == SH_CHECK_INIT)
[481]1174 sh_dbIO_data_write (tmpFile,
1175 (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
[1]1176 else
[294]1177 sh_hash_pushdata_memory (tmpFile,
1178 (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
[1]1179
[227]1180 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
1181 SH_FREE(tmpFile);
[1]1182 return;
1183}
1184
1185extern int sh_util_hextobinary (char * binary, char * hex, int bytes);
1186
[294]1187char * sh_hash_db2pop (const char * key, struct store2db * save)
[1]1188{
1189 size_t len;
1190 char * p;
1191 int i;
[167]1192 char * retval = NULL;
[294]1193 char fileHash[KEY_LEN+1];
[227]1194 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
[167]1195
[294]1196 save->size = 0;
[1]1197
[294]1198 if (0 == sh_hash_get_it (key, tmpFile, fileHash))
[1]1199 {
[294]1200 save->val0 = tmpFile->size;
1201 save->val1 = tmpFile->mtime;
1202 save->val2 = tmpFile->ctime;
1203 save->val3 = tmpFile->atime;
[1]1204
[294]1205 sl_strlcpy(save->checksum, fileHash, KEY_LEN+1);
1206
[227]1207 if (tmpFile->link_path && tmpFile->link_path[0] != '-')
[1]1208 {
[227]1209 len = strlen(tmpFile->link_path);
[1]1210
1211 p = SH_ALLOC((len/2)+1);
[227]1212 i = sh_util_hextobinary (p, tmpFile->link_path, len);
[1]1213
1214 if (i == 0)
1215 {
[294]1216 save->size = (len/2);
1217 p[save->size] = '\0';
[167]1218 retval = p;
[1]1219 }
1220 else
1221 {
1222 SH_FREE(p);
[294]1223 save->size = 0;
[1]1224 }
1225 }
1226 else
1227 {
[294]1228 save->size = 0;
[1]1229 }
1230 }
1231 else
1232 {
[294]1233 save->size = -1;
1234 save->val0 = 0;
1235 save->val1 = 0;
1236 save->val2 = 0;
1237 save->val3 = 0;
[1]1238 }
[227]1239 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
1240 SH_FREE(tmpFile);
[167]1241 return retval;
[1]1242}
1243
1244
1245
1246
1247/******************************************************************
1248 *
1249 * Data entry in hash table
1250 *
1251 ******************************************************************/
1252sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
1253{
1254 sh_file_t * fp;
1255 sh_filestore_t p;
[34]1256
1257 size_t len;
[1]1258 char * fullpath;
1259 char * linkpath;
[68]1260 char * attr_string = NULL;
[133]1261 char hashbuf[KEYBUF_SIZE];
[1]1262
1263 SL_ENTER(_("sh_hash_push_int"));
1264
1265 fp = SH_ALLOC(sizeof(sh_file_t));
1266
1267 p.mark = REC_MAGIC;
[68]1268 if (buf->attr_string)
1269 p.mark |= REC_FLAGS_ATTR;
[1]1270 sl_strlcpy(p.c_mode, buf->c_mode, 11);
1271 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
1272 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
1273 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
[10]1274#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]1275 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
1276#endif
1277
[10]1278#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]1279 p.attributes = (UINT32) buf->attributes;
1280#endif
1281 p.linkmode = (UINT32) buf->linkmode;
1282 p.hardlinks = (UINT32) buf->hardlinks;
[40]1283 p.dev = (UINT64) buf->dev;
1284 p.rdev = (UINT64) buf->rdev;
[1]1285 p.mode = (UINT32) buf->mode;
1286 p.ino = (UINT32) buf->ino;
1287 p.size = (UINT64) buf->size;
1288 p.mtime = (UINT64) buf->mtime;
1289 p.atime = (UINT64) buf->atime;
1290 p.ctime = (UINT64) buf->ctime;
1291 p.owner = (UINT32) buf->owner;
1292 p.group = (UINT32) buf->group;
1293
[481]1294 p.checkflags = (UINT32) buf->check_flags;
1295
[1]1296 memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
[115]1297 fp->fflags = 0; /* init fflags */
[1]1298 fp->modi_mask = 0L;
1299
[68]1300 if (buf->attr_string)
1301 attr_string = sh_util_strdup(buf->attr_string);
1302 fp->attr_string = attr_string;
1303
[34]1304 len = sl_strlen(buf->fullpath);
1305 if (len <= MAX_PATH_STORE)
[1]1306 {
[34]1307 fullpath = SH_ALLOC(len+1);
1308 sl_strlcpy(fullpath, buf->fullpath, len+1);
[1]1309 }
1310 else
1311 {
1312 fullpath = SH_ALLOC(KEY_LEN + 1);
1313 sl_strlcpy(fullpath,
[133]1314 sh_tiger_hash (buf->fullpath, TIGER_DATA, len,
1315 hashbuf, sizeof(hashbuf)),
[1]1316 KEY_LEN+1);
1317 }
1318 fp->fullpath = fullpath;
1319
[167]1320 if (buf->link_path)
[1]1321 {
[167]1322 len = sl_strlen(buf->link_path);
[34]1323 if (len <= MAX_PATH_STORE)
[1]1324 {
[34]1325 linkpath = SH_ALLOC(len+1);
[167]1326 sl_strlcpy(linkpath, buf->link_path, len+1);
[1]1327 }
1328 else
1329 {
1330 linkpath = SH_ALLOC(KEY_LEN + 1);
1331 sl_strlcpy(linkpath,
[167]1332 sh_tiger_hash (buf->link_path, TIGER_DATA, len,
[133]1333 hashbuf, sizeof(hashbuf)),
[1]1334 KEY_LEN+1);
1335 }
1336 fp->linkpath = linkpath;
1337 }
1338 else
1339 fp->linkpath = NULL;
1340
1341 SL_RETURN( fp, _("sh_hash_push_int"));
1342}
1343
1344#ifdef HAVE_INTTYPES_H
1345#include <inttypes.h>
1346#else
1347#ifdef HAVE_STDINT_H
1348#include <stdint.h>
1349#endif
1350#endif
1351
[40]1352#ifndef PRIu64
1353#ifdef HAVE_LONG_32
1354#define PRIu64 "llu"
1355#else
1356#define PRIu64 "lu"
[1]1357#endif
[40]1358#endif
[1]1359
1360char * sh_hash_size_format()
1361{
1362 static char form_rval[81];
1363
1364 SL_ENTER(_("sh_hash_size_format"));
1365
1366
1367#ifdef SH_USE_XML
1368 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
[40]1369 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
[1]1370#else
1371 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
[40]1372 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
[1]1373#endif
1374
1375 SL_RETURN( form_rval, _("sh_hash_size_format"));
1376}
1377
1378
1379#ifdef SH_USE_XML
1380static char * all_items (file_type * theFile, char * fileHash, int is_new)
1381{
1382 char timstr1c[32];
1383 char timstr1a[32];
1384 char timstr1m[32];
1385
1386 char * tmp_lnk;
1387 char * format;
1388
[170]1389 char * tmp = SH_ALLOC(SH_MSG_BUF);
1390 char * msg = SH_ALLOC(SH_MSG_BUF);
[1]1391
1392 tmp[0] = '\0';
1393 msg[0] = '\0';
1394
[481]1395 if (report_checkflags != S_FALSE)
1396 {
1397 if (is_new)
1398 format = _("checkflags_new=\"0%lo\" ");
1399 else
1400 format = _("checkflags_old=\"0%lo\" ");
1401 sl_snprintf(tmp, SH_MSG_BUF, format,
1402 (unsigned long) theFile->check_flags);
1403 sl_strlcat(msg, tmp, SH_MSG_BUF);
1404 }
[1]1405
[10]1406#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]1407 if (is_new)
1408 format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" ");
1409 else
1410 format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" ");
[170]1411 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1412 theFile->c_mode,
1413 theFile->c_attributes,
1414 (long) theFile->mode,
1415 (long) theFile->attributes
1416 );
1417#else
1418 if (is_new)
1419 format = _("mode_new=\"%s\" imode_new=\"%ld\" ");
1420 else
1421 format = _("mode_old=\"%s\" imode_old=\"%ld\" ");
1422
[170]1423 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1424 theFile->c_mode,
1425 (long) theFile->mode
1426 );
1427#endif
[170]1428 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1429
1430 if (is_new)
[40]1431 format = _("hardlinks_new=\"%lu\" ");
[1]1432 else
[40]1433 format = _("hardlinks_old=\"%lu\" ");
[170]1434 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1435 (unsigned long) theFile->hardlinks);
[170]1436 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1437
1438
1439 if (is_new)
[40]1440 format = _("idevice_new=\"%lu\" ");
[1]1441 else
[40]1442 format = _("idevice_old=\"%lu\" ");
[170]1443 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
1444 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1445
1446
1447 if (is_new)
[40]1448 format = _("inode_new=\"%lu\" ");
[1]1449 else
[40]1450 format = _("inode_old=\"%lu\" ");
[170]1451 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
1452 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1453
[40]1454 /*
1455 * also report device for prelude
1456 */
[181]1457#if defined(HAVE_LIBPRELUDE)
[40]1458 if (is_new)
1459 format = _("dev_new=\"%lu,%lu\" ");
1460 else
1461 format = _("dev_old=\"%lu,%lu\" ");
[170]1462 sl_snprintf(tmp, SH_MSG_BUF, format,
[40]1463 (unsigned long) major(theFile->dev),
1464 (unsigned long) minor(theFile->dev));
[170]1465 sl_strlcat(msg, tmp, SH_MSG_BUF);
[40]1466#endif
[1]1467
[40]1468
[1]1469 if (is_new)
1470 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
1471 else
1472 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
[170]1473 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1474 theFile->c_owner, (long) theFile->owner);
[170]1475 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1476
1477
1478 if (is_new)
1479 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
1480 else
1481 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
[170]1482 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1483 theFile->c_group, (long) theFile->group);
[170]1484 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1485
1486
1487 if (is_new)
[170]1488 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]1489 (UINT64) 0, (UINT64) theFile->size);
1490 else
[170]1491 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]1492 (UINT64) theFile->size, (UINT64) 0);
[170]1493 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1494
1495
[132]1496 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
[1]1497 if (is_new)
[170]1498 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=\"%s\" "), timstr1c);
[1]1499 else
[170]1500 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" "), timstr1c);
1501 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1502
[132]1503 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
[1]1504 if (is_new)
[170]1505 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=\"%s\" "), timstr1a);
[1]1506 else
[170]1507 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" "), timstr1a);
1508 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1509
[132]1510 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
[1]1511 if (is_new)
[170]1512 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=\"%s\" "), timstr1m);
[1]1513 else
[170]1514 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" "), timstr1m);
1515 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1516
1517 if (is_new)
[170]1518 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=\"%s\" "), fileHash);
[1]1519 else
[170]1520 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=\"%s\" "), fileHash);
1521 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1522
[169]1523 if (theFile->c_mode[0] == 'l' ||
1524 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
[1]1525 {
[167]1526 tmp_lnk = sh_util_safe_name(theFile->link_path);
[1]1527 if (tmp_lnk)
1528 {
1529 if (is_new)
[170]1530 sl_snprintf(tmp, SH_MSG_BUF, _("link_new=\"%s\" "), tmp_lnk);
[1]1531 else
[170]1532 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" "), tmp_lnk);
[1]1533 SH_FREE(tmp_lnk);
[170]1534 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1535 }
1536 }
[68]1537
1538 if (theFile->attr_string)
1539 {
1540 tmp_lnk = sh_util_safe_name(theFile->attr_string);
1541 if (tmp_lnk)
1542 {
1543 if (is_new)
[170]1544 sl_snprintf(tmp, SH_MSG_BUF, _("acl_new=\"%s\" "), tmp_lnk);
[68]1545 else
[170]1546 sl_snprintf(tmp, SH_MSG_BUF, _("acl_old=\"%s\" "), tmp_lnk);
[68]1547 SH_FREE(tmp_lnk);
[170]1548 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]1549 }
1550 }
1551
[1]1552
1553 SH_FREE(tmp);
1554 return (msg);
1555}
1556#else
1557static char * all_items (file_type * theFile, char * fileHash, int is_new)
1558{
1559 char timstr1c[32];
1560 char timstr1a[32];
1561 char timstr1m[32];
1562
1563 char * tmp_lnk;
1564 char * format;
1565
[170]1566 char * tmp = SH_ALLOC(SH_MSG_BUF);
1567 char * msg = SH_ALLOC(SH_MSG_BUF);
[1]1568
1569 tmp[0] = '\0';
1570 msg[0] = '\0';
1571
[481]1572 if (report_checkflags == S_TRUE)
1573 {
1574 if (is_new)
1575 format = _("checkflags_new=<0%lo> ");
1576 else
1577 format = _("checkflags_old=<0%lo> ");
1578 sl_snprintf(tmp, SH_MSG_BUF, format,
1579 (unsigned long) theFile->check_flags);
1580 sl_strlcat(msg, tmp, SH_MSG_BUF);
1581 }
[1]1582
[481]1583
[10]1584#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]1585 if (is_new)
1586 format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, ");
1587 else
1588 format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, ");
[170]1589 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1590 theFile->c_mode,
1591 theFile->c_attributes,
1592 (long) theFile->mode,
1593 (long) theFile->attributes
1594 );
1595#else
1596 if (is_new)
1597 format = _("mode_new=<%s>, imode_new=<%ld>, ");
1598 else
1599 format = _("mode_old=<%s>, imode_old=<%ld>, ");
1600
[170]1601 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1602 theFile->c_mode,
1603 (long) theFile->mode
1604 );
1605#endif
[170]1606 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1607
1608 if (is_new)
[40]1609 format = _("hardlinks_new=<%lu>, ");
[1]1610 else
[40]1611 format = _("hardlinks_old=<%lu>, ");
[170]1612 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1613 (unsigned long) theFile->hardlinks);
[170]1614 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1615
1616
1617 if (is_new)
[40]1618 format = _("idevice_new=<%lu>, ");
[1]1619 else
[40]1620 format = _("idevice_old=<%lu>, ");
[170]1621 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
1622 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1623
1624
1625 if (is_new)
[40]1626 format = _("inode_new=<%lu>, ");
[1]1627 else
[40]1628 format = _("inode_old=<%lu>, ");
[170]1629 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
1630 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1631
1632
[40]1633 /*
1634 * also report device for prelude
1635 */
[181]1636#if defined(HAVE_LIBPRELUDE)
[1]1637 if (is_new)
[40]1638 format = _("dev_new=<%lu,%lu>, ");
1639 else
1640 format = _("dev_old=<%lu,%lu>, ");
[170]1641 sl_snprintf(tmp, SH_MSG_BUF, format,
[40]1642 (unsigned long) major(theFile->dev),
1643 (unsigned long) minor(theFile->dev));
[170]1644 sl_strlcat(msg, tmp, SH_MSG_BUF);
[40]1645#endif
1646
1647 if (is_new)
[1]1648 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
1649 else
1650 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
[170]1651 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1652 theFile->c_owner, (long) theFile->owner);
[170]1653 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1654
1655
1656 if (is_new)
1657 format = _("group_new=<%s>, igroup_new=<%ld>, ");
1658 else
1659 format = _("group_old=<%s>, igroup_old=<%ld>, ");
[170]1660 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1661 theFile->c_group, (long) theFile->group);
[170]1662 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1663
1664
1665 if (is_new)
[170]1666 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]1667 (UINT64) 0, (UINT64) theFile->size);
1668 else
[170]1669 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]1670 (UINT64) theFile->size, (UINT64) 0);
[170]1671 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1672
1673
[132]1674 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
[1]1675 if (is_new)
[170]1676 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=<%s>, "), timstr1c);
[1]1677 else
[170]1678 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, "), timstr1c);
1679 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1680
[132]1681 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
[1]1682 if (is_new)
[170]1683 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=<%s>, "), timstr1a);
[1]1684 else
[170]1685 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, "), timstr1a);
1686 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1687
[132]1688 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
[1]1689 if (is_new)
[170]1690 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=<%s>, "), timstr1m);
[1]1691 else
[170]1692 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, "), timstr1m);
1693 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1694
1695 if (is_new)
[170]1696 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=<%s>"), fileHash);
[1]1697 else
[170]1698 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=<%s>"), fileHash);
1699 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1700
[169]1701 if (theFile->c_mode[0] == 'l' ||
1702 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
[1]1703 {
[167]1704 tmp_lnk = sh_util_safe_name(theFile->link_path);
[1]1705 if (tmp_lnk)
1706 {
1707 if (is_new)
[170]1708 sl_snprintf(tmp, SH_MSG_BUF, _(", link_new=<%s> "), tmp_lnk);
[1]1709 else
[170]1710 sl_snprintf(tmp, SH_MSG_BUF, _(", link_old=<%s> "), tmp_lnk);
[1]1711 SH_FREE(tmp_lnk);
[170]1712 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1713 }
1714 }
1715
[68]1716 if (theFile->attr_string)
1717 {
1718 tmp_lnk = sh_util_safe_name(theFile->attr_string);
1719 if (tmp_lnk)
1720 {
1721 if (is_new)
[170]1722 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_new=<%s> "), tmp_lnk);
[68]1723 else
[170]1724 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_old=<%s> "), tmp_lnk);
[68]1725 SH_FREE(tmp_lnk);
[170]1726 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]1727 }
1728 }
1729
[1]1730 SH_FREE(tmp);
1731 return (msg);
1732}
1733#endif
1734
1735void sh_hash_pushdata_memory (file_type * theFile, char * fileHash)
1736{
1737 sh_file_t * p;
1738
1739 SL_ENTER(_("sh_hash_pushdata_memory"));
1740
1741 p = sh_hash_push_int(theFile, fileHash);
1742 if (p)
1743 {
[149]1744 SH_MUTEX_LOCK(mutex_hash);
[481]1745 hashinsert (tab, p);
1746 p->modi_mask = theFile->check_flags;
[149]1747 SH_MUTEX_UNLOCK(mutex_hash);
[1]1748 }
1749
1750 SL_RET0(_("sh_hash_pushdata_memory"));
1751}
1752
[481]1753int sh_hash_is_null_file(file_type * theFile)
1754{
1755 if (theFile->hardlinks == SH_DEADFILE && theFile->mode == 0 &&
1756 theFile->ino == 0 && theFile->ctime == 0)
1757 {
1758 return S_TRUE;
1759 }
1760 return S_FALSE;
1761}
[1]1762
[481]1763int sh_hash_is_null_record(sh_filestore_t * theFile)
1764{
1765 if (theFile->hardlinks == SH_DEADFILE && theFile->mode == 0 &&
1766 theFile->ino == 0 && theFile->ctime == 0)
1767 {
1768 return S_TRUE;
1769 }
1770 return S_FALSE;
1771}
1772
1773void sh_hash_insert_null(char * str)
1774{
1775 file_type theFile = { 0, 0, {'\0'}, 0, 0, 0, 0, 0,
1776#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1777 0, {'\0'},
1778#endif
1779 {'\0'}, 0, {'\0'}, 0, {'\0'},
1780 0, 0, 0, 0, 0, 0, 0, NULL, 0, {'\0'}, 0, NULL
1781 }; /* clang compiler bails out on standard conforming init with just {0} */
1782 char fileHash[KEY_LEN+1];
1783 char hashbuf[KEYBUF_SIZE];
1784
1785 sl_strlcpy(fileHash, SH_KEY_NULL, sizeof(fileHash));
1786 theFile.hardlinks = SH_DEADFILE;
1787
1788 if (sl_strlen(str) < PATH_MAX)
1789 sl_strlcpy(theFile.fullpath, str, PATH_MAX);
1790 else
1791 sl_strlcpy(theFile.fullpath,
1792 sh_tiger_hash(str, TIGER_DATA, sl_strlen(str),
1793 hashbuf, sizeof(hashbuf)),
1794 PATH_MAX);
1795
1796 sh_hash_pushdata_memory(&theFile, fileHash);
1797 return;
1798}
1799
1800static int handle_notfound(int log_severity, int class,
1801 file_type * theFile, char * fileHash)
1802{
1803 sh_file_t * p;
1804 int retval = 0;
1805
1806 if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
1807 {
1808 char * tmp = sh_util_safe_name(theFile->fullpath);
1809 char * str;
1810
1811 sh_files_fixup_mask(class, &(theFile->check_flags));
1812 str = all_items (theFile, fileHash, 1);
1813
1814 sh_error_handle (log_severity, FIL__, __LINE__, 0,
1815 MSG_FI_ADD2,
1816 tmp, str);
1817 ++sh.statistics.files_report;
1818 SH_FREE(str);
1819 SH_FREE(tmp);
1820 }
1821
1822 if (sh.flag.reportonce == S_TRUE)
1823 SET_SH_FFLAG_REPORTED(theFile->file_reported);
1824
1825 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
1826 {
1827 p = sh_hash_push_int(theFile, fileHash);
1828 if (p)
1829 {
1830 hashinsert (tab, p);
1831 p->modi_mask = theFile->check_flags;
1832 p->theFile.checkflags = p->modi_mask;
1833 }
1834 }
1835
1836 else if (S_TRUE == sh.flag.update)
1837 {
1838 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
1839 {
1840 p = sh_hash_push_int(theFile, fileHash);
1841 if (p)
1842 {
1843 hashinsert (tab, p);
1844 p->modi_mask = theFile->check_flags;
1845 p->theFile.checkflags = p->modi_mask;
1846 }
1847 }
1848 else
1849 retval = 1;
1850 }
1851 return retval;
1852}
1853
[1]1854/*****************************************************************
1855 *
1856 * Compare a file with the database status.
1857 *
1858 *****************************************************************/
1859int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
1860 char * policy_override, int severity_override)
1861{
1862 char * msg;
1863 sh_file_t * p;
1864 char * tmp;
1865 char * tmp_path;
1866 char * tmp_lnk;
1867 char * tmp_lnk_old;
1868
1869 char timstr1c[32];
1870 char timstr2c[32];
1871 char timstr1a[32];
1872 char timstr2a[32];
1873 char timstr1m[32];
1874 char timstr2m[32];
1875 char linkHash[KEY_LEN+1];
[169]1876 char * linkComp;
[1]1877 int maxcomp;
1878
1879 char change_code[16];
1880 int i;
1881
[170]1882 unsigned long modi_mask;
[1]1883
1884 char log_policy[32];
[153]1885 volatile int log_severity;
[133]1886 char hashbuf[KEYBUF_SIZE];
[481]1887 struct {
1888 unsigned long oldflags;
1889 unsigned long newflags;
1890 } cf_report;
[1]1891
[170]1892 int retval;
[149]1893
[1]1894 SL_ENTER(_("sh_hash_compdata"));
1895
1896 if (IsInit != 1) sh_hash_init();
1897
1898 if (severity_override < 0)
1899 log_severity = ShDFLevel[class];
1900 else
1901 log_severity = severity_override;
1902
1903 if (policy_override != NULL)
1904 sl_strlcpy (log_policy, policy_override, 32);
1905
1906 /* -------- find the entry for the file ---------------- */
1907
[149]1908 SH_MUTEX_LOCK(mutex_hash);
1909
[170]1910 modi_mask = 0;
1911 retval = 0;
1912
[1]1913 if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE)
1914 p = hashsearch(theFile->fullpath);
1915 else
1916 p = hashsearch( sh_tiger_hash(theFile->fullpath,
1917 TIGER_DATA,
[133]1918 sl_strlen(theFile->fullpath),
1919 hashbuf, sizeof(hashbuf))
[1]1920 );
1921
1922
1923 /* --------- Not found in database. ------------
1924 */
1925
1926 if (p == NULL)
1927 {
[481]1928 retval = handle_notfound(log_severity, class, theFile, fileHash);
[149]1929 goto unlock_and_return;
[1]1930 }
1931
[425]1932 /* --------- Skip if we don't want to report changes. ------------
1933 */
1934
1935 if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
1936 {
[481]1937 MODI_SET(theFile->check_flags, MODI_NOCHECK);
1938 p->modi_mask = theFile->check_flags;
1939 p->theFile.checkflags = p->modi_mask;
[425]1940 goto unlock_and_return;
1941 }
1942
[481]1943 cf_report.oldflags = p->theFile.checkflags;
1944 cf_report.newflags = theFile->check_flags;
[149]1945
[481]1946 p->modi_mask = theFile->check_flags;
1947 p->theFile.checkflags = p->modi_mask;
1948
[1]1949 /* initialize change_code */
1950 for (i = 0; i < 15; ++i)
1951 change_code[i] = '-';
1952 change_code[15] = '\0';
1953
1954 TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"),
1955 theFile->fullpath, fileHash, p->theFile.checksum));
1956
[474]1957 if ( (fileHash != NULL) &&
[19]1958 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
[481]1959 (theFile->check_flags & MODI_CHK) != 0)
[1]1960 {
[481]1961 if ((theFile->check_flags & MODI_SGROW) == 0)
[19]1962 {
1963 modi_mask |= MODI_CHK;
1964 change_code[0] = 'C';
1965 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
1966 }
1967 else
1968 {
[425]1969 if (0 != strncmp (&fileHash[KEY_LEN + 1], p->theFile.checksum, KEY_LEN))
[19]1970 {
[425]1971 if (S_FALSE == sh_check_rotated_log (theFile->fullpath, (UINT64) p->theFile.size,
[481]1972 (UINT64) p->theFile.ino, p->theFile.checksum,
1973 p->theFile.checkflags))
[425]1974 {
1975 modi_mask |= MODI_CHK;
1976 change_code[0] = 'C';
1977 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
1978 }
1979 else
1980 {
1981 /* logfile has been rotated */
1982 p->theFile.size = theFile->size;
1983 p->theFile.ino = theFile->ino;
1984 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
1985 }
[19]1986 }
1987 else
1988 {
1989 p->theFile.size = theFile->size;
1990 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
1991 }
1992 }
[1]1993 }
1994
1995 if (p->theFile.c_mode[0] == 'l')
1996 {
[169]1997 if (!(theFile->link_path) &&
[481]1998 (theFile->check_flags & MODI_LNK) != 0)
[1]1999 {
[169]2000 linkComp = NULL;
[93]2001 modi_mask |= MODI_LNK;
2002 change_code[1] = 'L';
2003 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
[169]2004 }
2005 else
2006 {
2007 if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE)
2008 {
2009 sl_strlcpy(linkHash,
2010 sh_tiger_hash(theFile->link_path,
2011 TIGER_DATA,
2012 sl_strlen(theFile->link_path),
2013 hashbuf, sizeof(hashbuf)),
2014 MAX_PATH_STORE+1);
2015 linkComp = linkHash;
2016 maxcomp = KEY_LEN;
2017 }
2018 else
2019 {
2020 linkComp = theFile->link_path;
2021 maxcomp = MAX_PATH_STORE;
2022 }
2023
2024 if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 &&
[481]2025 (theFile->check_flags & MODI_LNK) != 0)
[169]2026 {
2027 modi_mask |= MODI_LNK;
2028 change_code[1] = 'L';
2029 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2030 }
2031 }
[1]2032 }
2033
2034 if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b')
2035 {
2036 if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) ||
2037 minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
[481]2038 (theFile->check_flags & MODI_RDEV) != 0)
[1]2039 {
2040 modi_mask |= MODI_RDEV;
2041 change_code[2] = 'D';
2042 TPT ((0, FIL__, __LINE__, _("mod=<rdev>")));
2043 }
2044 }
2045
2046 /* cast to UINT32 in case ino_t is not 32bit
2047 */
2048 if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino &&
[481]2049 (theFile->check_flags & MODI_INO) != 0)
[1]2050 {
2051 modi_mask |= MODI_INO;
2052 change_code[3] = 'I';
2053 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2054 }
2055
2056 if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
[481]2057 (theFile->check_flags & MODI_HLN) != 0)
[1]2058 {
2059 modi_mask |= MODI_HLN;
2060 change_code[4] = 'H';
2061 TPT ((0, FIL__, __LINE__, _("mod=<hardlink>")));
2062 }
2063
2064
2065 if ( ( (theFile->mode != p->theFile.mode)
[68]2066#if defined(USE_ACL) || defined(USE_XATTR)
2067 || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
2068 (
2069 (theFile->attr_string == NULL && p->attr_string != NULL) ||
2070 (theFile->attr_string != NULL && p->attr_string == NULL) ||
2071 (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
2072 )
2073 )
2074#endif
[10]2075#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2076 || (theFile->attributes != p->theFile.attributes)
2077#endif
[68]2078 )
[481]2079 && (theFile->check_flags & MODI_MOD) != 0)
[1]2080 {
2081 modi_mask |= MODI_MOD;
2082 change_code[5] = 'M';
2083 TPT ((0, FIL__, __LINE__, _("mod=<mode>")));
2084 /*
2085 * report link path if switch link/no link
2086 */
[481]2087 if ((theFile->check_flags & MODI_LNK) != 0 &&
[1]2088 (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
2089 (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
2090 {
2091 modi_mask |= MODI_LNK;
2092 change_code[1] = 'L';
2093 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2094 }
2095 }
2096
2097 if ( theFile->owner != (uid_t) p->theFile.owner &&
[481]2098 (theFile->check_flags & MODI_USR) != 0)
[1]2099 {
2100 modi_mask |= MODI_USR;
2101 change_code[6] = 'U';
2102 TPT ((0, FIL__, __LINE__, _("mod=<user>")));
2103 }
2104
2105 if ( theFile->group != (gid_t) p->theFile.group &&
[481]2106 (theFile->check_flags & MODI_GRP) != 0)
[1]2107 {
2108 modi_mask |= MODI_GRP;
2109 change_code[7] = 'G';
2110 TPT ((0, FIL__, __LINE__, _("mod=<group>")));
2111 }
2112
2113
2114 if ( theFile->mtime != (time_t) p->theFile.mtime &&
[481]2115 (theFile->check_flags & MODI_MTM) != 0)
[1]2116 {
2117 modi_mask |= MODI_MTM;
2118 change_code[8] = 'T';
2119 TPT ((0, FIL__, __LINE__, _("mod=<mtime>")));
2120 }
2121
[481]2122 if ( (theFile->check_flags & MODI_ATM) != 0 &&
[68]2123 theFile->atime != (time_t) p->theFile.atime)
[1]2124 {
2125 modi_mask |= MODI_ATM;
2126 change_code[8] = 'T';
2127 TPT ((0, FIL__, __LINE__, _("mod=<atime>")));
2128 }
2129
2130
2131 /* Resetting the access time will set a new ctime. Thus, either we ignore
2132 * the access time or the ctime for NOIGNORE
2133 */
2134 if ( theFile->ctime != (time_t) p->theFile.ctime &&
[481]2135 (theFile->check_flags & MODI_CTM) != 0)
[1]2136 {
2137 modi_mask |= MODI_CTM;
2138 change_code[8] = 'T';
2139 TPT ((0, FIL__, __LINE__, _("mod=<ctime>")));
2140 }
2141
2142 if ( theFile->size != (off_t) p->theFile.size &&
[481]2143 (theFile->check_flags & MODI_SIZ) != 0)
[1]2144 {
[481]2145 if ((theFile->check_flags & MODI_SGROW) == 0 ||
[19]2146 theFile->size < (off_t) p->theFile.size)
[1]2147 {
2148 modi_mask |= MODI_SIZ;
2149 change_code[9] = 'S';
2150 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
[19]2151 }
[1]2152 }
2153 change_code[10] = '\0';
2154
[205]2155 /* --- Directories special case ---
2156 */
2157 if (p->theFile.c_mode[0] == 'd' &&
2158 0 == (modi_mask & ~(MODI_SIZ|MODI_ATM|MODI_CTM|MODI_MTM)) &&
2159 sh_loosedircheck == S_TRUE)
2160 {
2161 modi_mask = 0;
2162 }
2163
[1]2164 /* --- Report full details. ---
2165 */
2166 if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
2167 {
[481]2168 if ((theFile->check_flags & MODI_ATM) == 0)
[1]2169 modi_mask = MASK_READONLY_;
2170 else
2171 modi_mask = MASK_NOIGNORE_;
2172 }
2173
2174 /* --- Report on modified files. ---
2175 */
[114]2176 if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
[1]2177 {
[170]2178 tmp = SH_ALLOC(SH_MSG_BUF);
2179 msg = SH_ALLOC(SH_MSG_BUF);
[1]2180 msg[0] = '\0';
2181
[481]2182 sh_files_fixup_mask(class, &(cf_report.newflags));
2183
2184 if ( (report_checkflags != S_FALSE) && (cf_report.oldflags != cf_report.newflags))
2185 {
2186 sl_snprintf(tmp, SH_MSG_BUF,
2187#ifdef SH_USE_XML
2188 _("checkflags_old=\"0%lo\" checkflags_new=\"0%lo\" "),
2189#else
2190 _("checkflags_old=<0%lo>, checkflags_new=<0%lo>, "),
2191#endif
2192 cf_report.oldflags, cf_report.newflags);
2193 sl_strlcat(msg, tmp, SH_MSG_BUF);
2194 }
2195
[1]2196 if ( ((modi_mask & MODI_MOD) != 0)
[181]2197#if defined(HAVE_LIBPRELUDE)
[68]2198 || ((modi_mask & MODI_USR) != 0)
2199 || ((modi_mask & MODI_GRP) != 0)
[1]2200#endif
2201 )
2202 {
[10]2203#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[170]2204 sl_snprintf(tmp, SH_MSG_BUF,
[1]2205#ifdef SH_USE_XML
2206 _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "),
2207#else
2208 _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "),
2209#endif
2210 p->theFile.c_mode, theFile->c_mode,
2211 p->theFile.c_attributes, theFile->c_attributes
2212#ifdef SH_USE_XML
2213 , (long) p->theFile.mode, (long) theFile->mode,
2214 (long) p->theFile.attributes,
2215 (long) theFile->attributes
2216#endif
2217 );
2218#else
2219#ifdef SH_USE_XML
[170]2220 sl_snprintf(tmp, SH_MSG_BUF,
[1]2221 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
[68]2222 p->theFile.c_mode, theFile->c_mode,
2223 (long) p->theFile.mode, (long) theFile->mode);
[1]2224#else
[170]2225 sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=<%s>, mode_new=<%s>, "),
[68]2226 p->theFile.c_mode, theFile->c_mode);
[1]2227#endif
[68]2228#endif
[170]2229 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]2230
2231#if defined(USE_ACL) || defined(USE_XATTR)
2232 if (theFile->attr_string != NULL || p->attr_string != NULL)
2233 {
[170]2234 sl_snprintf(tmp, SH_MSG_BUF,
[1]2235#ifdef SH_USE_XML
[68]2236 _("acl_old=\"%s\" acl_new=\"%s\" "),
2237#else
2238 _("acl_old=<%s>, acl_new=<%s>, "),
[1]2239#endif
[68]2240 (p->attr_string) ? p->attr_string : _("none"),
2241 (theFile->attr_string) ? theFile->attr_string : _("none"));
2242
[170]2243 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]2244 }
[1]2245#endif
[68]2246
[1]2247 if ((modi_mask & MODI_MOD) != 0)
2248 {
2249 /*
2250 * We postpone update if sh.flag.update == S_TRUE because
2251 * in interactive mode the user may not accept the change.
2252 */
2253 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2254 {
2255 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
2256 p->theFile.mode = theFile->mode;
[10]2257#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2258 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
2259 p->theFile.attributes = theFile->attributes;
2260#endif
[68]2261#if defined(USE_ACL) || defined(USE_XATTR)
2262 if (p->attr_string == NULL && theFile->attr_string != NULL)
2263 { p->attr_string = sh_util_strdup (theFile->attr_string); }
2264 else if (p->attr_string != NULL && theFile->attr_string == NULL)
2265 { SH_FREE(p->attr_string); p->attr_string = NULL; }
2266 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2267 {
2268 if (0 != strcmp(theFile->attr_string, p->attr_string))
2269 {
2270 SH_FREE(p->attr_string);
2271 p->attr_string = sh_util_strdup (theFile->attr_string);
2272 }
2273 }
2274#endif
[1]2275 }
2276 }
[481]2277
[1]2278 }
2279
2280 if ((modi_mask & MODI_HLN) != 0)
2281 {
[170]2282 sl_snprintf(tmp, SH_MSG_BUF,
[1]2283#ifdef SH_USE_XML
[40]2284 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
[1]2285#else
[40]2286 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
[1]2287#endif
2288 (unsigned long) p->theFile.hardlinks,
2289 (unsigned long) theFile->hardlinks);
[170]2290 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2291
[1]2292 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2293 p->theFile.hardlinks = theFile->hardlinks;
2294 }
2295
2296 if ((modi_mask & MODI_RDEV) != 0)
2297 {
[170]2298 sl_snprintf(tmp, SH_MSG_BUF,
[1]2299#ifdef SH_USE_XML
[40]2300 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
[1]2301#else
[40]2302 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
[1]2303#endif
2304 (unsigned long) major(p->theFile.rdev),
2305 (unsigned long) minor(p->theFile.rdev),
2306 (unsigned long) major(theFile->rdev),
2307 (unsigned long) minor(theFile->rdev)
2308#ifdef SH_USE_XML
2309 , (unsigned long) p->theFile.rdev,
2310 (unsigned long) theFile->rdev
2311#endif
2312 );
[170]2313 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2314
[1]2315 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2316 p->theFile.rdev = theFile->rdev;
2317 }
2318
2319 if ((modi_mask & MODI_INO) != 0)
2320 {
[170]2321 sl_snprintf(tmp, SH_MSG_BUF,
[1]2322#ifdef SH_USE_XML
[40]2323 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
[1]2324#else
[40]2325 _("inode_old=<%lu>, inode_new=<%lu>, "),
[1]2326#endif
2327 (unsigned long) p->theFile.ino,
2328 (unsigned long) theFile->ino);
[170]2329 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2330
[1]2331 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
[40]2332 {
2333 p->theFile.ino = theFile->ino;
2334 p->theFile.dev = theFile->dev;
2335 }
[1]2336 }
2337
[40]2338
2339 /*
2340 * also report device for prelude
2341 */
[181]2342#if defined(HAVE_LIBPRELUDE)
[40]2343 if ((modi_mask & MODI_INO) != 0)
2344 {
[170]2345 sl_snprintf(tmp, SH_MSG_BUF,
[40]2346#ifdef SH_USE_XML
2347 _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "),
2348#else
2349 _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "),
2350#endif
2351 (unsigned long) major(p->theFile.dev),
2352 (unsigned long) minor(p->theFile.dev),
2353 (unsigned long) major(theFile->dev),
2354 (unsigned long) minor(theFile->dev)
2355 );
[170]2356 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2357
[40]2358 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2359 p->theFile.dev = theFile->dev;
2360 }
2361#endif
2362
[1]2363 if ( ((modi_mask & MODI_USR) != 0)
[181]2364#if defined(HAVE_LIBPRELUDE)
[1]2365 || ((modi_mask & MODI_MOD) != 0)
2366#endif
2367 )
2368 {
2369#ifdef SH_USE_XML
[170]2370 sl_snprintf(tmp, SH_MSG_BUF,
[40]2371 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
[1]2372#else
[170]2373 sl_snprintf(tmp, SH_MSG_BUF,
[40]2374 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
[1]2375#endif
[40]2376 p->theFile.c_owner, theFile->c_owner,
2377 (long) p->theFile.owner, (long) theFile->owner
[1]2378 );
[170]2379 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2380
[1]2381 if ((modi_mask & MODI_USR) != 0) {
2382 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2383 {
2384 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
2385 p->theFile.owner = theFile->owner;
2386 }
2387 }
2388 }
2389
2390 if ( ((modi_mask & MODI_GRP) != 0)
[181]2391#if defined(HAVE_LIBPRELUDE)
[1]2392 || ((modi_mask & MODI_MOD) != 0)
2393#endif
2394 )
2395 {
2396#ifdef SH_USE_XML
[170]2397 sl_snprintf(tmp, SH_MSG_BUF,
[40]2398 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
[1]2399 p->theFile.c_group, theFile->c_group,
2400 (long) p->theFile.group, (long) theFile->group);
2401#else
[170]2402 sl_snprintf(tmp, SH_MSG_BUF,
[40]2403 _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "),
2404 p->theFile.c_group, theFile->c_group,
2405 (long) p->theFile.group, (long) theFile->group);
[1]2406#endif
2407
[170]2408 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2409
[1]2410 if ((modi_mask & MODI_GRP) != 0) {
2411 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2412 {
2413 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
2414 p->theFile.group = theFile->group;
2415 }
2416 }
2417 }
2418
2419 if ((modi_mask & MODI_SIZ) != 0)
2420 {
[170]2421 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]2422 (UINT64) p->theFile.size,
2423 (UINT64) theFile->size);
[170]2424 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2425
[1]2426 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2427 p->theFile.size = theFile->size;
2428 }
2429
2430 if ((modi_mask & MODI_CTM) != 0)
2431 {
[132]2432 (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c));
2433 (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c));
[1]2434#ifdef SH_USE_XML
[170]2435 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
[1]2436 timstr1c, timstr2c);
2437#else
[170]2438 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, ctime_new=<%s>, "),
[1]2439 timstr1c, timstr2c);
2440#endif
[170]2441 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2442
[1]2443 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2444 p->theFile.ctime = theFile->ctime;
2445 }
2446
2447 if ((modi_mask & MODI_ATM) != 0)
2448 {
[132]2449 (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a));
2450 (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a));
[1]2451#ifdef SH_USE_XML
[170]2452 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" atime_new=\"%s\" "),
[1]2453 timstr1a, timstr2a);
2454#else
[170]2455 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, atime_new=<%s>, "),
[1]2456 timstr1a, timstr2a);
2457#endif
[170]2458 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2459
[1]2460 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2461 p->theFile.atime = theFile->atime;
2462 }
2463
2464 if ((modi_mask & MODI_MTM) != 0)
2465 {
[132]2466 (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m));
2467 (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m));
[1]2468#ifdef SH_USE_XML
[170]2469 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
[1]2470 timstr1m, timstr2m);
2471#else
[170]2472 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, mtime_new=<%s>, "),
[1]2473 timstr1m, timstr2m);
2474#endif
[170]2475 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2476
[1]2477 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2478 p->theFile.mtime = theFile->mtime;
2479 }
2480
2481
2482 if ((modi_mask & MODI_CHK) != 0)
2483 {
[170]2484 sl_snprintf(tmp, SH_MSG_BUF,
[1]2485#ifdef SH_USE_XML
2486 _("chksum_old=\"%s\" chksum_new=\"%s\" "),
2487#else
2488 _("chksum_old=<%s>, chksum_new=<%s>, "),
2489#endif
2490 p->theFile.checksum, fileHash);
[170]2491 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2492
[1]2493 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
[107]2494 {
2495 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
[481]2496 if ((theFile->check_flags & MODI_SGROW) != 0)
[107]2497 p->theFile.size = theFile->size;
2498 }
[481]2499
2500
[169]2501 if (theFile->c_mode[0] != 'l' && theFile->link_path &&
2502 strlen(theFile->link_path) > 2)
2503 modi_mask |= MODI_LNK;
[1]2504 }
2505
2506
[169]2507 if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */)
[1]2508 {
[169]2509 if (theFile->link_path)
2510 tmp_lnk = sh_util_safe_name(theFile->link_path);
2511 else
2512 tmp_lnk = sh_util_strdup("-");
2513 if (p->linkpath)
2514 tmp_lnk_old = sh_util_safe_name(p->linkpath);
2515 else
2516 tmp_lnk_old = sh_util_strdup("-");
[1]2517#ifdef SH_USE_XML
[170]2518 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" link_new=\"%s\" "),
[1]2519 tmp_lnk_old, tmp_lnk);
2520#else
[294]2521 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=<%s>, link_new=<%s>, "),
[1]2522 tmp_lnk_old, tmp_lnk);
2523#endif
2524 SH_FREE(tmp_lnk);
2525 SH_FREE(tmp_lnk_old);
[170]2526 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2527
[1]2528 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2529 {
[481]2530 if (p->linkpath != NULL)
[1]2531 SH_FREE(p->linkpath);
[481]2532 if (!(theFile->link_path))
2533 p->linkpath = sh_util_strdup("-");
[149]2534 else
[167]2535 p->linkpath = sh_util_strdup(theFile->link_path);
[1]2536 }
2537 }
2538
[481]2539 if (MODI_AUDIT_ENABLED(theFile->check_flags))
[294]2540 {
2541 char result[256];
[1]2542
[294]2543 if (NULL != sh_audit_fetch (theFile->fullpath, theFile->mtime, result, sizeof(result)))
2544 {
2545#ifdef SH_USE_XML
2546 sl_strlcat(msg, _("obj=\""), SH_MSG_BUF);
2547#else
2548 sl_strlcat(msg, _("obj=<"), SH_MSG_BUF);
2549#endif
2550
2551 sl_strlcat(msg, result, SH_MSG_BUF);
2552
2553#ifdef SH_USE_XML
2554 sl_strlcat(msg, _("\" "), SH_MSG_BUF);
2555#else
2556 sl_strlcat(msg, _(">"), SH_MSG_BUF);
2557#endif
2558 }
2559 }
2560
[481]2561 /****************************************************
2562 *
2563 * REPORT on file change
2564 *
2565 ****************************************************/
[1]2566 tmp_path = sh_util_safe_name(theFile->fullpath);
2567 sh_error_handle(log_severity, FIL__, __LINE__,
2568 (long) modi_mask, MSG_FI_CHAN,
2569 (policy_override == NULL) ? _(policy[class]):log_policy,
2570 change_code, tmp_path, msg);
[405]2571 ++sh.statistics.files_report;
[1]2572
2573 SH_FREE(tmp_path);
2574 SH_FREE(tmp);
2575 SH_FREE(msg);
2576
2577 if (S_TRUE == sh.flag.update)
2578 {
2579 if (S_FALSE == sh_util_ask_update(theFile->fullpath))
2580 {
2581 /* user does not want to update, thus we replace
2582 * with data from the baseline database
2583 */
2584 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
2585 theFile->mode = p->theFile.mode;
[10]2586#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2587 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
2588 theFile->attributes = p->theFile.attributes;
2589#endif
[68]2590#if defined(USE_ACL) || defined(USE_XATTR)
2591 if (theFile->attr_string == NULL && p->attr_string != NULL)
2592 { theFile->attr_string = sh_util_strdup (p->attr_string); }
2593 else if (theFile->attr_string != NULL && p->attr_string == NULL)
2594 { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
2595 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2596 {
2597 if (0 != strcmp(theFile->attr_string, p->attr_string))
2598 {
2599 SH_FREE(theFile->attr_string);
2600 theFile->attr_string = sh_util_strdup (p->attr_string);
2601 }
2602 }
2603#endif
[1]2604
2605 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
2606 {
[167]2607 if (theFile->link_path)
2608 SH_FREE(theFile->link_path);
2609 if (p->linkpath)
2610 theFile->link_path = sh_util_strdup(p->linkpath);
2611 else
2612 theFile->link_path = sh_util_strdup("-");
[1]2613 }
2614 else
2615 {
[167]2616 if (theFile->link_path)
2617 SH_FREE(theFile->link_path);
[481]2618 if (p->linkpath)
[167]2619 theFile->link_path = sh_util_strdup(p->linkpath);
2620 else
2621 theFile->link_path = NULL;
[1]2622 }
2623
2624 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
2625
2626 theFile->mtime = p->theFile.mtime;
2627 theFile->ctime = p->theFile.ctime;
2628 theFile->atime = p->theFile.atime;
2629
2630 theFile->size = p->theFile.size;
2631
2632 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
2633 theFile->group = p->theFile.group;
2634 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
2635 theFile->owner = p->theFile.owner;
2636
2637 theFile->ino = p->theFile.ino;
2638 theFile->rdev = p->theFile.rdev;
2639 theFile->dev = p->theFile.dev;
2640 theFile->hardlinks = p->theFile.hardlinks;
2641
[114]2642 SET_SH_FFLAG_VISITED(p->fflags);
2643 CLEAR_SH_FFLAG_CHECKED(p->fflags);
[149]2644 retval = 1;
2645 goto unlock_and_return;
[1]2646 }
[77]2647 else /* if (sh.flag.reportonce == S_TRUE) */
[1]2648 {
2649 /* we replace the data in the in-memory copy of the
2650 * baseline database, because otherwise we would get
2651 * another warning if the suidcheck runs
2652 */
2653 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
2654 p->theFile.mode = theFile->mode;
[10]2655#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2656 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
2657 p->theFile.attributes = theFile->attributes;
2658#endif
[68]2659#if defined(USE_ACL) || defined(USE_XATTR)
2660 if (p->attr_string == NULL && theFile->attr_string != NULL)
2661 { p->attr_string = sh_util_strdup (theFile->attr_string); }
2662 else if (p->attr_string != NULL && theFile->attr_string == NULL)
2663 { SH_FREE(p->attr_string); p->attr_string = NULL; }
2664 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2665 {
2666 if (0 != strcmp(theFile->attr_string, p->attr_string))
2667 {
2668 SH_FREE(p->attr_string);
2669 p->attr_string = sh_util_strdup (theFile->attr_string);
2670 }
2671 }
2672#endif
[1]2673
[167]2674 if (theFile->c_mode[0] == 'l' || theFile->link_path)
[1]2675 {
[481]2676 if (p->linkpath != NULL)
[1]2677 SH_FREE(p->linkpath);
[167]2678 p->linkpath = sh_util_strdup(theFile->link_path);
[1]2679 }
2680 else
2681 {
[481]2682 if (p->linkpath != NULL)
[167]2683 SH_FREE(p->linkpath);
[481]2684 p->linkpath = sh_util_strdup("-");
[1]2685 }
2686
2687 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2688
2689 p->theFile.mtime = theFile->mtime;
2690 p->theFile.ctime = theFile->ctime;
2691 p->theFile.atime = theFile->atime;
2692
2693 p->theFile.size = theFile->size;
2694
2695 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
2696 p->theFile.group = theFile->group;
2697 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
2698 p->theFile.owner = theFile->owner;
2699
2700 p->theFile.ino = theFile->ino;
2701 p->theFile.rdev = theFile->rdev;
2702 p->theFile.dev = theFile->dev;
2703 p->theFile.hardlinks = theFile->hardlinks;
2704 }
2705 }
2706 }
2707
[114]2708 SET_SH_FFLAG_VISITED(p->fflags);
2709 CLEAR_SH_FFLAG_CHECKED(p->fflags);
[1]2710
[149]2711 unlock_and_return:
[153]2712 ; /* 'label at end of compound statement */
[149]2713 SH_MUTEX_UNLOCK(mutex_hash);
2714 SL_RETURN(retval, _("sh_hash_compdata"));
[1]2715}
2716
2717int hash_full_tree ()
2718{
2719 sh_file_t * p;
2720 int i;
2721
[457]2722 SL_ENTER(_("hash_full_tree"));
[1]2723
2724 if (IsInit != 1)
[457]2725 SL_RETURN(0, _("hash_full_tree"));
[1]2726
[149]2727 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
[1]2728 for (i = 0; i < TABSIZE; ++i)
2729 {
2730 for (p = tab[i]; p; p = p->next)
[114]2731 CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
[1]2732 }
[149]2733 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
[457]2734 SL_RETURN (0, _("hash_full_tree"));
[1]2735}
2736
[457]2737#if !defined(SH_CUTEST)
2738static
2739#endif
2740int hash_remove_tree_test(char * s, char * fullpath, size_t len_s)
2741{
2742 size_t len_p;
2743 char * test;
[1]2744
[457]2745 len_p = strlen(fullpath);
2746
2747 if (len_p >= len_s)
2748 {
2749 if (0 == strncmp(s, fullpath, len_s))
2750 {
2751 if (len_p > len_s)
2752 {
2753 /* continue if not inside directory;
2754 * len_s > 1 because everything is inside '/'
2755 */
2756 if ((len_s > 1) && (fullpath[len_s] != '/'))
2757 return S_FALSE;
2758
2759 test = sh_files_find_mostspecific_dir(fullpath);
2760
2761 if (test && 0 != strcmp(test, s)) {
2762 /* There is a more specific directory, continue */
2763 return S_FALSE;
2764 }
2765
2766 if (NULL == sh_files_findfile(fullpath)) {
2767 /* SET_SH_FFLAG_ALLIGNORE(p->fflags); */
2768 return S_TRUE;
2769 }
2770 }
2771 else /* len_p == len */
2772 {
2773 /* it is 's' itself, mark and continue
2774 * unless there is a policy for the inode itself
2775 */
2776 if (NULL == sh_files_findfile(fullpath)) {
2777 /* SET_SH_FFLAG_ALLIGNORE(p->fflags); */
2778 return S_TRUE;
2779 }
2780 else {
2781 return S_FALSE;
2782 }
2783 }
2784
2785 } /* if path is in tree */
2786 } /* if path is possibly in tree */
2787 return S_FALSE;
2788}
2789
2790
[1]2791int hash_remove_tree (char * s)
2792{
[8]2793 sh_file_t * p;
[457]2794 size_t len_s;
[8]2795 unsigned int i;
[1]2796
2797 SL_ENTER(_("hash_remove_tree"));
2798
[8]2799 if (!s || *s == '\0')
[1]2800 SL_RETURN ((-1), _("hash_remove_tree"));
2801
[457]2802 len_s = sl_strlen(s);
[8]2803
[1]2804 if (IsInit != 1)
2805 sh_hash_init();
2806
[149]2807 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
[1]2808 for (i = 0; i < TABSIZE; ++i)
2809 {
2810 for (p = tab[i]; p; p = p->next)
2811 {
[457]2812 if (p->fullpath)
2813 {
2814 /* if (0 == strncmp(s, p->fullpath, len_s)) *//* old */
[481]2815 if (S_TRUE == hash_remove_tree_test(s, p->fullpath, len_s)) {
[457]2816 SET_SH_FFLAG_ALLIGNORE(p->fflags);
[481]2817 MODI_SET(p->theFile.checkflags, MODI_ALLIGNORE);
2818 }
[457]2819 } /* if path is not null */
2820
[1]2821 }
2822 }
[149]2823 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
[1]2824 SL_RETURN ((0), _("hash_remove_tree"));
2825}
2826
2827#if TIME_WITH_SYS_TIME
2828#include <sys/time.h>
2829#include <time.h>
2830#else
2831#if HAVE_SYS_TIME_H
2832#include <sys/time.h>
2833#else
2834#include <time.h>
2835#endif
2836#endif
2837
[169]2838static int ListFullDetail = S_FALSE;
[1]2839static int ListWithDelimiter = S_FALSE;
[169]2840static char * ListFile = NULL;
[1]2841
[169]2842int set_list_file (const char * c)
2843{
2844 ListFile = sh_util_strdup(c);
2845 return 0;
2846}
[481]2847char * get_list_file()
2848{
2849 return ListFile;
2850}
[169]2851
[20]2852int set_full_detail (const char * c)
[1]2853{
[149]2854 (void) c;
[1]2855 ListFullDetail = S_TRUE;
[149]2856 return 0;
[1]2857}
2858
[20]2859int set_list_delimited (const char * c)
[1]2860{
[149]2861 (void) c;
[1]2862 ListFullDetail = S_TRUE;
2863 ListWithDelimiter = S_TRUE;
[149]2864 return 0;
[1]2865}
[76]2866
[149]2867/* Always quote the string, except if it is empty. Quote quotes by
[76]2868 * doubling them.
2869 */
2870char * csv_escape(const char * str)
2871{
2872 const char * p = str;
2873 const char * q;
2874
2875 size_t size = 0;
2876 size_t flag_quote = 0;
[362]2877
[76]2878 char * new;
2879 char * pnew;
2880
2881 if (p)
2882 {
2883
2884 while (*p)
2885 {
[362]2886 if (*p == '"')
[76]2887 ++flag_quote;
2888
2889 ++size; ++p;
2890 }
2891
2892 if (sl_ok_adds(size, flag_quote))
2893 size += flag_quote; /* double each quote */
2894 else
2895 return NULL;
2896
2897 if (sl_ok_adds(size, 3))
2898 size += 3; /* two quotes and terminating null */
2899 else
2900 return NULL;
2901
2902 new = SH_ALLOC(size);
2903
2904 if (flag_quote != 0)
2905 {
2906 new[0] = '"';
2907 pnew = &new[1];
2908 q = str;
2909 while (*q)
2910 {
2911 *pnew = *q;
2912 if (*pnew == '"')
2913 {
2914 ++pnew; *pnew = '"';
2915 }
2916 ++pnew; ++q;
2917 }
2918 *pnew = '"'; ++pnew;
2919 *pnew = '\0';
2920 }
2921 else
2922 {
2923 if (size > 3)
2924 {
2925 new[0] = '"';
2926 sl_strlcpy (&new[1], str, size-1);
2927 new[size-2] = '"';
2928 new[size-1] = '\0';
2929 }
2930 else
2931 {
2932 new[0] = '\0';
2933 }
2934 }
2935
2936 return new;
2937 }
2938 return NULL;
2939}
2940
[444]2941int isHexKey(char * s)
2942{
2943 int i;
2944
2945 for (i = 0; i < KEY_LEN; ++i)
2946 {
2947 if (*s)
2948 {
2949 if ((*s >= '0' && *s <= '9') ||
2950 (*s >= 'A' && *s <= 'F') ||
2951 (*s >= 'a' && *s <= 'f'))
2952 {
2953 ++s;
2954 continue;
2955 }
2956 }
2957 return S_FALSE;
2958 }
2959 return S_TRUE;
2960}
2961
2962#include "sh_checksum.h"
[76]2963
[444]2964static char * KEYBUFtolower (char * s, char * result)
2965{
2966 char * r = result;
2967 if (s)
2968 {
2969 for (; *s; ++s)
2970 {
2971 *r = tolower((unsigned char) *s); ++r;
2972 }
2973 *r = '\0';
2974 }
2975 return result;
2976}
2977
[1]2978void sh_hash_list_db_entry_full_detail (sh_file_t * p)
2979{
2980 char * tmp;
[76]2981 char * esc;
[1]2982 char str[81];
[444]2983 char hexdigest[SHA256_DIGEST_STRING_LENGTH];
2984 char keybuffer[KEYBUF_SIZE];
[1]2985
2986 if (ListWithDelimiter == S_TRUE)
2987 {
[40]2988 printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "),
2989 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
[1]2990 p->theFile.c_mode, (int) p->theFile.mode,
2991 p->theFile.c_attributes, (int) p->theFile.attributes,
2992 (int) p->theFile.hardlinks,
2993 p->theFile.c_owner, (int) p->theFile.owner,
2994 p->theFile.c_group, (int) p->theFile.group);
2995 }
2996 else
2997 {
[40]2998 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
2999 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
[1]3000 p->theFile.c_mode, (int) p->theFile.mode,
3001 p->theFile.c_attributes, (int) p->theFile.attributes,
3002 (int) p->theFile.hardlinks,
3003 p->theFile.c_owner, (int) p->theFile.owner,
3004 p->theFile.c_group, (int) p->theFile.group);
3005 }
3006
3007 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
[132]3008 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev);
[1]3009 else
[132]3010 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size);
[1]3011
3012 printf( _(" %8s"), str);
3013 if (ListWithDelimiter == S_TRUE)
3014 putchar(',');
3015
[132]3016 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str)));
[1]3017 if (ListWithDelimiter == S_TRUE)
3018 putchar(',');
[132]3019 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str)));
[1]3020 if (ListWithDelimiter == S_TRUE)
3021 putchar(',');
[132]3022 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str)));
[1]3023 if (ListWithDelimiter == S_TRUE)
3024 putchar(',');
[444]3025
3026 if (isHexKey(p->theFile.checksum))
3027 printf( _(" %s"), KEYBUFtolower(p->theFile.checksum, keybuffer));
3028 else
3029 printf( _(" %s"), SHA256_Base2Hex(p->theFile.checksum, hexdigest));
[1]3030 if (ListWithDelimiter == S_TRUE)
3031 putchar(',');
3032
3033 tmp = sh_util_safe_name(p->fullpath);
[76]3034 if (ListWithDelimiter != S_TRUE)
3035 {
3036 printf( _(" %s"), tmp);
3037 }
3038 else
3039 {
3040 esc = csv_escape(tmp);
3041 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3042 if (esc)
3043 SH_FREE(esc);
3044 }
[1]3045 SH_FREE(tmp);
3046
3047 if ('l' == p->theFile.c_mode[0])
3048 {
3049 tmp = sh_util_safe_name(p->linkpath);
[76]3050 if (ListWithDelimiter != S_TRUE)
3051 {
3052 printf(_(" -> %s"), tmp);
3053 }
[1]3054 else
[76]3055 {
3056 esc = csv_escape(tmp);
3057 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3058 if (esc)
3059 SH_FREE(esc);
3060 }
[1]3061 SH_FREE(tmp);
3062 }
[68]3063
3064 if (p->attr_string)
3065 {
3066 tmp = sh_util_safe_name(p->attr_string);
[76]3067 if (ListWithDelimiter != S_TRUE)
3068 {
3069 printf(_(" %s"), tmp);
3070 }
3071 else
3072 {
3073 esc = csv_escape(tmp);
3074 printf( _(" %s"), (esc != NULL) ? esc : _("(null)"));
3075 if (esc)
3076 SH_FREE(esc);
3077 }
[68]3078 SH_FREE(tmp);
3079 }
[1]3080 else
[68]3081 {
3082 if (ListWithDelimiter == S_TRUE)
[210]3083 printf("%s",_(" no_attr"));
[68]3084 }
3085 putchar('\n');
[1]3086
3087 return;
3088}
3089
3090void sh_hash_list_db_entry (sh_file_t * p)
3091{
3092 char nowtime[128];
3093 char thetime[128];
3094 char * tmp;
3095 time_t now = time(NULL);
3096 time_t then = (time_t) p->theFile.mtime;
[481]3097 struct tm * time_ptr;
[1]3098
[131]3099#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
3100 struct tm time_tm;
[481]3101#endif
[131]3102
[481]3103 if (ListFullDetail != S_FALSE)
3104 {
3105 sh_hash_list_db_entry_full_detail (p);
3106 return;
3107 }
3108
3109#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
[131]3110 time_ptr = gmtime_r(&then, &time_tm);
[481]3111 if (!time_ptr)
3112 return;
[131]3113 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
3114 time_ptr = gmtime_r(&now, &time_tm);
[481]3115 if (!time_ptr)
3116 return;
[131]3117 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
3118 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3119 {
3120 time_ptr = gmtime_r(&then, &time_tm);
[481]3121 if (!time_ptr)
3122 return;
[131]3123 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
3124 }
3125#else
[481]3126 time_ptr = gmtime(&then);
3127 if (!time_ptr)
3128 return;
3129 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
3130 time_ptr = gmtime(&now);
3131 if (!time_ptr)
3132 return;
3133 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
[1]3134 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
[481]3135 {
3136 time_ptr = gmtime(&then);
3137 if (!time_ptr)
3138 return;
3139 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
3140 }
[131]3141#endif
[1]3142
3143 tmp = sh_util_safe_name(p->fullpath);
3144 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3145 printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"),
3146 p->theFile.c_mode, (int) p->theFile.hardlinks,
3147 p->theFile.c_owner, p->theFile.c_group,
3148 (int) major((dev_t)p->theFile.rdev),
3149 (int) minor((dev_t)p->theFile.rdev),
3150 thetime,
3151 tmp);
3152 else
3153 printf(_("%10s %3d %-8s %-8s %8ld %s %s"),
3154 p->theFile.c_mode, (int) p->theFile.hardlinks,
3155 p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size,
3156 thetime,
3157 tmp);
3158 SH_FREE(tmp);
3159
3160 if ('l' == p->theFile.c_mode[0])
3161 {
3162 tmp = sh_util_safe_name(p->linkpath);
3163 printf(_(" -> %s\n"), tmp);
3164 SH_FREE(tmp);
3165 }
3166 else
3167 printf("\n");
3168
3169 return;
3170}
3171
[169]3172#ifdef HAVE_LIBZ
3173#include <zlib.h>
3174#endif
3175
3176int sh_hash_printcontent(char * linkpath)
3177{
3178#ifdef HAVE_LIBZ
3179 unsigned char * decoded;
3180 unsigned char * decompressed = NULL;
3181 size_t dlen;
3182 unsigned long clen;
3183 unsigned long clen_o;
3184 int res;
3185
3186 if (linkpath && *linkpath != '-')
3187 {
3188 dlen = sh_util_base64_dec_alloc (&decoded,
3189 (unsigned char *)linkpath,
3190 strlen(linkpath));
[170]3191
[169]3192 clen = dlen * 2 + 1;
[170]3193
[169]3194 do {
3195 if (decompressed)
3196 SH_FREE(decompressed);
3197 clen += dlen; clen_o = clen;
3198 decompressed = SH_ALLOC(clen);
3199 res = uncompress(decompressed, &clen, decoded, dlen);
3200 if (res == Z_MEM_ERROR)
[210]3201 { fprintf(stderr, "%s",_("Error: Not enough memory\n")); return -1; }
[169]3202 if (res == Z_DATA_ERROR)
[210]3203 { fprintf(stderr, "%s",_("Error: Data corrupt or incomplete\n")); return -1; }
[169]3204 } while (res == Z_BUF_ERROR || clen == clen_o);
[170]3205
[169]3206 decompressed[clen] = '\0';
3207 fputs( (char*) decompressed, stdout);
[227]3208 SH_FREE(decompressed);
[169]3209 return 0;
3210 }
3211#else
3212 (void) linkpath;
3213#endif
[210]3214 fprintf(stderr, "%s",_("Error: No data available\n"));
[169]3215 return -1;
3216}
3217
[1]3218/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
3219#endif
Note: See TracBrowser for help on using the repository browser.