source: trunk/src/sh_dbIO.c@ 494

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

Fix for ticket #389 (libwrap) and #390 (update on FreeBSD).

File size: 41.9 KB
RevLine 
[481]1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2015 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 <stdio.h>
23#include <string.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <unistd.h>
27
28#include "samhain.h"
29#include "sh_utils.h"
30#include "sh_dbIO_int.h"
31#include "sh_hash.h"
32#include "sh_dbIO.h"
33#include "sh_gpg.h"
34#include "sh_tiger.h"
35#include "sh_xfer.h"
36#include "sh_pthread.h"
37#include "sh_socket.h"
38#include "sh_files.h"
39
40#undef FIL__
41#define FIL__ _("sh_dbIO.c")
42
43#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
44
45/* external prototypes */
46
47extern int get_the_fd (SL_TICKET ticket);
48
49SH_MUTEX_EXTERN(mutex_hash);
50
51/******************************************************************
52 *
53 * Get a single line
54 *
55 ******************************************************************/
56static FILE * sh_fin_fd = NULL;
57
58int sh_dbIO_getline (FILE * fd, char * line, const size_t sizeofline)
59{
60 size_t n = 0;
61
62 SL_REQUIRE(sizeofline >= SH_MINIBUF, _("sizeofline >= SH_MINIBUF"));
63
64 if (NULL != fgets(line, sizeofline, fd))
65 {
66 n = strlen(line);
67 if (n > 0 && line[n-1] == '\n') {
68 n--; line[n] = '\0';
69 }
70 }
71 else {
72 line[0] = '\0';
73 return -1;
74 }
75
76 return n;
77}
78
79/******************************************************************
80 *
81 * Fast forward to start of data
82 *
83 ******************************************************************/
84
85static void reopen_fin_fd(SL_TICKET fd)
86{
87 if (sh_fin_fd != NULL)
88 {
89 sl_fclose (FIL__, __LINE__, sh_fin_fd);
90 sh_fin_fd = NULL;
91 }
92
93 sh_fin_fd = fdopen(dup(get_the_fd(fd)), "rb");
94 return;
95}
96
97
98static int seek_sof(FILE * fd, char * line, int size, const char * file)
99{
100 long i;
101
102 while (1)
103 {
104 i = sh_dbIO_getline (fd, line, size);
105 if (i < 0 )
106 {
107 SH_FREE(line);
108 dlog(1, FIL__, __LINE__,
109 _("The file signature database: %s does not\ncontain any data, or the start-of-file marker is missing (unlikely,\nunless modified by hand).\n"),
110 (NULL == file) ? _("(null)") : file);
111
112 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
113 ( (NULL == file) ? _("(null)") : file)
114 );
115 return -1;
116 }
117
118#if defined(SH_STEALTH)
119 if (0 == sl_strncmp (line, N_("[SOF]"), 5))
120#else
121 if (0 == sl_strncmp (line, _("[SOF]"), 5))
122#endif
123 break;
124 }
125 fflush(fd);
126 return 0;
127}
128
129static int sh_dbIO_setdataent (SL_TICKET fd, char * line, int size,
130 const char * file)
131{
132 int retval;
133
134 SL_ENTER(_("sh_dbIO_setdataent"));
135
136 sl_rewind (fd);
137 reopen_fin_fd(fd);
138
139 if (!sh_fin_fd)
140 {
141 dlog(1, FIL__, __LINE__,
142 _("The file signature database: %s is not readable.\n"),
143 (NULL == file) ? _("(null)") : file);
144 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
145 ( (NULL == file) ? _("(null)") : file)
146 );
147 SL_RETURN( -1, _("sh_dbIO_setdataent"));
148 }
149
150 retval = seek_sof(sh_fin_fd, line, size, file);
151 SL_RETURN( retval, _("sh_dbIO_setdataent"));
152}
153
154static int sh_dbIO_setdataent_old (SL_TICKET fd, char * line, int size,
155 const char * file)
156{
157 FILE * fdp;
[491]158
[481]159 SL_ENTER(_("sh_dbIO_setdataent_old"));
160
161 sl_rewind (fd);
162 fdp = sl_stream(fd, "r+");
163 if (0 != seek_sof(fdp, line, size, file))
164 SL_RETURN( SL_EREAD, _("sh_dbIO_setdataent_old"));
[491]165
166 lseek(fileno(fdp), ftello(fdp), SEEK_SET);
167
[481]168 if (0 != ftruncate(fileno(fdp), ftello(fdp)))
169 {
170 char ebuf[SH_ERRBUF_SIZE];
171 int errnum = errno;
172 sh_error_message(errnum, ebuf, sizeof(ebuf));
173 sh_error_handle ((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN,
174 ebuf, _("sh_dbIO_setdataent_old") );
175 SL_RETURN( SL_EWRITE, _("sh_dbIO_setdataent_old"));
176 }
177 SL_RETURN( 0, _("sh_dbIO_setdataent_old"));
178}
179
180/******************************************************************
181 *
182 * IO helper functions
183 *
184 ******************************************************************/
185
186
187static UINT32 * swap_32 (UINT32 * iptr)
188{
189#ifdef WORDS_BIGENDIAN
190 unsigned char swap;
191 unsigned char * ii = (unsigned char *) iptr;
192 swap = ii[0]; ii[0] = ii[3]; ii[3] = swap;
193 swap = ii[1]; ii[1] = ii[2]; ii[2] = swap;
194 return iptr;
195#else
196 return iptr;
197#endif
198}
199
200static UINT64 * swap_64 (UINT64 * iptr)
201{
202#ifdef WORDS_BIGENDIAN
203#ifdef UINT64_IS_32
204 swap_32 ((UINT32*) iptr);
205#else
206 unsigned char swap;
207 unsigned char * ii = (unsigned char *) iptr;
208 swap = ii[0]; ii[0] = ii[7]; ii[7] = swap;
209 swap = ii[1]; ii[1] = ii[6]; ii[6] = swap;
210 swap = ii[2]; ii[2] = ii[5]; ii[5] = swap;
211 swap = ii[3]; ii[3] = ii[4]; ii[4] = swap;
212#endif
213 return iptr;
214#else
215 return iptr;
216#endif
217}
218
219static unsigned short * swap_short (unsigned short * iptr)
220{
221#ifdef WORDS_BIGENDIAN
222 if (sizeof(short) == 4)
223 swap_32 ((UINT32*) iptr);
224 else
225 {
226 /* alignment problem */
227 unsigned char swap;
228 static unsigned short ooop;
229 unsigned char * ii;
230 ooop = *iptr;
231 ii = (unsigned char *) &ooop;
232 swap = ii[0]; ii[0] = ii[1]; ii[1] = swap;
233 return &ooop;
234 }
235 return iptr;
236#else
237 return iptr;
238#endif
239}
240
241static void swap_data(sh_filestore_t * ft)
242{
243 swap_32(&(ft->mode));
244 swap_32(&(ft->linkmode));
245 swap_64(&(ft->dev));
246 swap_64(&(ft->rdev));
247 swap_32(&(ft->hardlinks));
248 swap_32(&(ft->ino));
249 swap_64(&(ft->size));
250 swap_64(&(ft->atime));
251 swap_64(&(ft->mtime));
252 swap_64(&(ft->ctime));
253 swap_32(&(ft->owner));
254 swap_32(&(ft->group));
255 swap_32(&(ft->checkflags));
256#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
257 swap_32(&(ft->attributes));
258#endif
259 ft->mark = *(swap_short(&(ft->mark)));
260 return;
261}
262
263#define QUOTE_CHAR '='
264
265char * unquote_string (const char * str, size_t len)
266{
267 int i = 0, t1, t2;
268 char * tmp = NULL;
269 size_t l2, j, k = 0;
270
271 SL_ENTER(_("unquote_string"));
272
273 if (str != NULL)
274 {
275 l2 = len - 2;
276 tmp = SH_ALLOC(len + 1);
277
278 for (j = 0; j <= len; ++j)
279 {
280 if (str[j] != QUOTE_CHAR)
281 {
282 tmp[k] = str[j];
283 }
284 else if (str[j] == QUOTE_CHAR && j < l2)
285 {
286 t1 = sh_util_hexchar(str[j+1]);
287 t2 = sh_util_hexchar(str[j+2]);
288 if ((t1|t2) >= 0)
289 {
290 i = 16 * t1 + t2;
291 tmp[k] = i;
292 j += 2;
293 }
294 else
295 {
296 tmp[k] = str[j];
297 }
298 }
299 else
300 tmp[k] = str[j];
301 ++k;
302 }
303 }
304 SL_RETURN(tmp, _("unquote_string"));
305}
306
307static char * int2hex (unsigned char i, char * i2h)
308{
309 static char hexchars[] = "0123456789ABCDEF";
310
311 i2h[0] = hexchars[(((i) & 0xF0) >> 4)]; /* high */
312 i2h[1] = hexchars[((i) & 0x0F)]; /* low */
313
314 return i2h;
315}
316
317char * quote_string (const char * str, size_t len)
318{
319 char * tmp;
320 char * tmp2;
321 size_t l2, j, i = 0, k = 0;
322 char i2h[2];
323
324 SL_ENTER(_("quote_string"));
325
326 if (str == NULL)
327 {
328 SL_RETURN(NULL, _("quote_string"));
329 }
330
331 for (j = 0; j < len; ++j)
332 if (str[j] == '\n' || str[j] == QUOTE_CHAR) ++i;
333
334 l2 = len + 1;
335 if (sl_ok_muls(3, i) && sl_ok_adds(l2, (3*i)))
336 {
337 tmp = SH_ALLOC(len + 1 + 3*i);
338 }
339 else
340 {
341 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
342 _("integer overflow"),
343 _("quote_string"));
344 SL_RETURN(NULL, _("quote_string"));
345 }
346
347 for (j = 0; j <= len; ++j)
348 {
349 if (str[j] == '\n')
350 {
351 tmp2 = int2hex((unsigned char) '\n', i2h);
352 tmp[k] = QUOTE_CHAR; ++k;
353 tmp[k] = tmp2[0]; ++k;
354 tmp[k] = tmp2[1];
355 }
356 else if (str[j] == QUOTE_CHAR)
357 {
358 tmp2 = int2hex((unsigned char) QUOTE_CHAR, i2h);
359 tmp[k] = QUOTE_CHAR; ++k;
360 tmp[k] = tmp2[0]; ++k;
361 tmp[k] = tmp2[1];
362 }
363 else
364 {
365 tmp[k] = str[j];
366 }
367 ++k;
368 }
369 SL_RETURN(tmp, _("quote_string"));
370}
371
372static char * unquote_path(char * line, long i)
373{
374 char * tmp = unquote_string (line, i);
375 size_t len = sl_strlen(tmp)+1;
376 char * path = SH_ALLOC(len);
377
378 (void) sl_strlcpy (path, tmp, len);
379 if (tmp)
380 SH_FREE(tmp);
381 if (len > 1) {
382 if (path[len-2] == '\n')
383 path[len-2] = '\0';
384 }
385 return path;
386}
387
388/******************************************************************
389 *
390 * Read next record and return it
391 *
392 ******************************************************************/
393
394static void corrupt_record(char * file, int line, const char * filepath)
395{
396 dlog(1, file, line,
397 _("There is a corrupt record in the file signature database: %s\n"),
398 (NULL == filepath)? _("(null)") : filepath);
399 sh_error_handle ((-1), file, line, 0, MSG_E_SUBGPATH,
400 _("Corrupt record in file signature database"),
401 _("sh_dbIO_getdataent"),
402 ( (NULL == filepath) ? _("(null)") : filepath) );
403 return;
404}
405
406static void wrong_version(char * file, int line, const char * filepath)
407{
408 dlog(1, file, line,
409 _("There is a record with a bad version number in the file signature database: %s\n"),
410 (NULL == filepath) ? _("(null)") : filepath);
[491]411 sh_error_handle((-1), file, line, 0, MSG_E_SUBGPATH,
[481]412 _("Record with bad version number in file signature database"),
413 _("sh_dbIO_getdataent"),
414 (NULL == filepath) ? _("(null)") : filepath);
415 return;
416}
417
[483]418static void hexdump(unsigned char * data, size_t size)
419{
420 unsigned int count =0;
421 char ith[3];
422
423 do {
424 int2hex(data[count], ith); ith[2] = '\0';
425 printf("%2s", ith);
426 ++count;
427 if (count % 40 == 0) putc('\n', stdout);
428 } while (count < size);
429}
430
[481]431static size_t dbIO_fread_struct (sh_filestore_t * ptr, FILE *stream,
432 const char * path, int * errflag)
433{
434 sh_filestore_old_t old_struct;
435 fpos_t position;
436 static int oldflag = -1;
437
438 start:
439 if (oldflag != -1) /* 'initialized' case first */
440 {
441 if (oldflag == 0)
442 return fread (ptr, sizeof(sh_filestore_t), 1, stream);
443
444 else
445 {
446 unsigned short mark;
447 if (1 != fread (&old_struct, sizeof(old_struct), 1, stream))
448 return 0;
449
450 /* set mark to current version */
451 mark = old_struct.mark;
452 mark = *(swap_short(&(mark)));
453 if ((mark & ~REC_FLAGS_MASK) != OLD_REC_MAGIC)
454 {
455 sh_filestore_old_t try_struct;
456 char try[5];
457
[483]458 if (1 == 0)
459 hexdump((unsigned char *)&old_struct, sizeof(old_struct));
[481]460 memset(&try_struct, '\0', sizeof(try_struct));
461 if (!memcmp(&old_struct, &try_struct, sizeof(try_struct)))
462 return 0; /* NULL read */
463 if (1 != fread (try, sizeof(try), 1, stream))
464 return 0;
465 if (feof(stream))
466 return 0;
467
468 wrong_version(FIL__, __LINE__, path);
469 *errflag = -1;
470 return 0;
471 }
472 if ((mark & REC_FLAGS_ATTR) != 0)
473 mark = REC_MAGIC|REC_FLAGS_ATTR;
474 else
475 mark = REC_MAGIC;
476 mark = *(swap_short(&(mark)));
477 old_struct.mark = mark;
478
479 /* copy into current struct version */
480 memcpy(ptr, &old_struct, sizeof(old_struct));
481 ptr->checkflags = 0;
482 return 1;
483 }
484 }
485 else /* not initialized yet, test DB version */
486 {
487 if (0 == fgetpos(stream, &position))
488 {
489 unsigned short mark;
490
491 if (1 != fread (&old_struct, sizeof(old_struct), 1, stream))
492 return 0;
493
494 mark = old_struct.mark;
495 mark = *(swap_short(&(mark)));
496 if ((mark & ~REC_FLAGS_MASK) == REC_MAGIC)
497 oldflag = 0;
498 else if ((mark & ~REC_FLAGS_MASK) == OLD_REC_MAGIC)
499 oldflag = 1;
500 else
501 {
502 wrong_version(FIL__, __LINE__, path);
503 *errflag = -1;
504 return 0;
505 }
506
507 /* return to previous position and read data */
508 if (0 != fsetpos(stream, &position))
509 return 0;
510 goto start;
511 }
512 return 0;
513 }
514}
515
516int sig_end_detected (void * ft)
517{
518 char * str = (char *) ft;
519 char cmp[SH_MINIBUF];
520
521 sl_strlcpy(cmp, _("-----BEGIN PGP SIGNATURE-----"), sizeof(cmp));
522
523 if ( 0 == memcmp(str, cmp, strlen(cmp)) )
524 return S_TRUE;
525 return S_FALSE;
526}
527
528static sh_file_t * sh_dbIO_getdataent (char * line, int size,
529 const char * filepath, int * errflag)
530{
531 sh_file_t * p;
532 sh_filestore_t ft;
533 long i;
534 char * fullpath;
535 char * linkpath;
536 char * attr_string = NULL;
537
538 SL_ENTER(_("sh_dbIO_getdataent"));
539
540 *errflag = 0;
541
542 p = SH_ALLOC(sizeof(sh_file_t));
543
544 /* Read next record -- Part One
545 */
546 if (1 != dbIO_fread_struct (&ft, sh_fin_fd, filepath, errflag))
547 {
548 SH_FREE(p);
549 SL_RETURN( NULL, _("sh_dbIO_getdataent"));
550 }
551
552 ft.mark = *(swap_short(&(ft.mark)));
553
554 if ((ft.mark & ~REC_FLAGS_MASK) != REC_MAGIC)
555 {
556 if (sig_end_detected(&ft))
557 {
558 SH_FREE(p);
559 SL_RETURN( NULL, _("sh_dbIO_getdataent"));
560 }
561 SH_FREE(p);
562 wrong_version(FIL__, __LINE__, filepath);
563 *errflag = -1;
564 SL_RETURN( NULL, _("sh_dbIO_getdataent"));
565 }
566
567 ft.mark = *(swap_short(&(ft.mark)));
568 swap_data(&ft);
569
570 /* Read next record -- Part Two -- Fullpath
571 */
572 i = sh_dbIO_getline (sh_fin_fd, line, size);
573
574 if (i <= 0 )
575 {
576 SH_FREE(p);
577 corrupt_record(FIL__, __LINE__, filepath);
578 *errflag = -1;
579 SL_RETURN( NULL, _("sh_dbIO_getdataent"));
580 }
581
582 fullpath = unquote_path(line, i);
583
584 /* Read next record -- Part Three -- Linkpath
585 */
586 i = sh_dbIO_getline (sh_fin_fd, line, size);
587
588 if (i <= 0 )
589 {
590 SH_FREE(fullpath); SH_FREE(p);
591 corrupt_record(FIL__, __LINE__, filepath);
592 *errflag = -1;
593 SL_RETURN( NULL, _("sh_dbIO_getdataent"));
594 }
595
596 linkpath = unquote_path(line, i);
597
598 /* Read next record -- Part Four -- attr_string
599 */
600 if ((ft.mark & REC_FLAGS_ATTR) != 0)
601 {
602 i = sh_dbIO_getline (sh_fin_fd, line, size);
603 if (i <= 0 )
604 {
605 SH_FREE(fullpath); SH_FREE(linkpath); SH_FREE(p);
606 corrupt_record(FIL__, __LINE__, filepath);
607 *errflag = -1;
608 SL_RETURN( NULL, _("sh_dbIO_getdataent"));
609 }
610
611 attr_string = unquote_path(line, i);
612 }
613
614 /* Read next record -- Part Four -- Decode
615 */
616#if defined(SH_STEALTH)
617 sh_do_decode(fullpath, sl_strlen(fullpath));
618#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
619 sh_do_decode(ft.c_attributes, sl_strlen(ft.c_attributes));
620#endif
621 sh_do_decode(ft.c_mode, sl_strlen(ft.c_mode));
622 sh_do_decode(ft.c_owner, sl_strlen(ft.c_owner));
623 sh_do_decode(ft.c_group, sl_strlen(ft.c_group));
624 sh_do_decode(ft.checksum, sl_strlen(ft.checksum));
625 /*
626 * TXT entries are c_mode[0] != 'l' and do not get decoded
627 */
628 if (ft.c_mode[0] == 'l' && linkpath[0] != '-')
629 {
630 sh_do_decode(linkpath, sl_strlen(linkpath));
631 }
632 if ((ft.mark & REC_FLAGS_ATTR) != 0)
633 {
634 sh_do_decode(attr_string, sl_strlen(attr_string));
635 }
636#endif
637
638 memcpy( &(*p).theFile, &ft, sizeof(sh_filestore_t) );
639
640 /* init fflags, such that suid files in
641 * database are recognized as such
642 */
643 {
644 mode_t mode = (mode_t) ft.mode;
645
646 if (S_ISREG(mode) &&
647 (0 !=(S_ISUID & mode) ||
648#if defined(HOST_IS_LINUX)
649 (0 !=(S_ISGID & mode) &&
650 0 !=(S_IXGRP & mode))
651#else
652 0 !=(S_ISGID & mode)
653#endif
654 )
655 )
656 p->fflags = SH_FFLAG_SUIDCHK;
657
658 else
659 p->fflags = 0;
660 }
661
662 p->modi_mask = ft.checkflags;
663 if (MODI_ISSET(ft.checkflags, MODI_ALLIGNORE))
664 SET_SH_FFLAG_ALLIGNORE(p->fflags);
665 p->fullpath = fullpath;
666 p->linkpath = linkpath;
667 p->attr_string = attr_string;
668
669 /* set to an invalid value
670 */
671 ft.mark = (REC_MAGIC + 5);
672
673 SL_REQUIRE((*errflag == 0), _("errflag not set correctly"));
674 SL_RETURN( p, _("sh_dbIO_getdataent"));
675}
676
677/******************************************************************
678 *
679 * Data loading routines
680 *
681 ******************************************************************/
682static SL_TICKET load_data_from_server(const char * uuid)
683{
684 SL_TICKET fd = -1;
685
686#if defined(SH_WITH_CLIENT)
687 char hashbuf[KEYBUF_SIZE];
688
689 /* Data file from Server
690 */
691 if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
692 return -1;
693
694 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_D_DSTART);
695 fd = sh_xfer_request_file((!uuid) ? _("DATA") : uuid);
696
697 if (SL_ISERROR(fd))
698 {
699 if (!uuid)
700 {
701 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FBAD);
702 dlog(1, FIL__, __LINE__,
703 _("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);
704 }
705 else
706 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_TCP_FBAD);
707 return fd;
708 }
709 sl_rewind (fd);
710
711 if (!uuid)
712 {
713 sl_strlcpy (sh.data.hash,
714 sh_tiger_hash (file_path('D', 'R'),
715 fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
716 KEY_LEN+1);
717 sl_rewind (fd);
718 }
719#else
720 (void) uuid;
721#endif
722 return fd;
723}
724
725static SL_TICKET load_data_from_disk(const char * filepath)
726{
727 char hashbuf[KEYBUF_SIZE];
728 SL_TICKET fd = -1;
729
730 /* Local data file
731 */
732 if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, filepath, SL_YESPRIV)) )
733 {
734 TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s>\n"), filepath));
735 dlog(1, FIL__, __LINE__,
736 _("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"),
737 sl_get_errmsg(), fd, (int) sl_ret_euid());
738 sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1,
739 sh.prg_name);
740 return -1;
741 }
742
743 TPT(( 0, FIL__, __LINE__, _("msg=<Opened database: %s>\n"),
744 filepath));
745
746 if (sh.data.hash[0] == '\0')
747 {
748 char hashbuf[KEYBUF_SIZE];
749 sl_strlcpy(sh.data.hash,
750 sh_tiger_hash (filepath, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
751 KEY_LEN+1);
752 }
753 else
754 {
755 if (0 != sl_strncmp(sh.data.hash,
756 sh_tiger_hash (filepath, fd, TIGER_NOLIM,
757 hashbuf, sizeof(hashbuf)),
758 KEY_LEN)
759 && sh.flag.checkSum != SH_CHECK_INIT)
760 {
761 dlog(1, FIL__, __LINE__,
762 _("The checksum of the file signature database has changed since startup: %s -> %s\n"),
763 sh.data.hash, sh_tiger_hash (filepath, fd, TIGER_NOLIM,
764 hashbuf, sizeof(hashbuf)));
765 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH,
766 ( (NULL == filepath) ? _("(null)") :
767 filepath )
768 );
769 }
770 }
771 sl_rewind (fd);
772 return fd;
773}
774
775static SL_TICKET verify_data (SL_TICKET fd)
776{
777#if defined(WITH_GPG) || defined(WITH_PGP)
778 SL_TICKET fdTmp;
779
780 /* extract the data and copy to temporary file
781 */
782 fdTmp = sh_gpg_extract_signed(fd);
783
784 if (sig_termfast == 1) /* SIGTERM */
785 {
786 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
787 --sig_raised; --sig_urgent;
788 return -1;
789 }
790
791 sl_close(fd);
792 fd = fdTmp;
793
794 /* Validate signature of open file.
795 */
796 if (0 != sh_gpg_check_sign (fd, SIG_DATA))
797 {
798 sl_close(fd);
799 return -1;
800 }
801 sl_rewind (fd);
802#endif
803
804 return fd;
805}
806
807static int read_data(SL_TICKET fd, sh_file_t * tab[TABSIZE],
808 const char * filepath)
809{
810 sh_file_t * p;
811 int count = 0;
812 int errflag = 0;
813 char * line = SH_ALLOC(MAX_PATH_STORE+2);
814
815 /* fast forward to start of data
816 */
817 if (0 != sh_dbIO_setdataent(fd, line, MAX_PATH_STORE+1, filepath))
818 return -1;
819
820 while (1)
821 {
822 if (sig_termfast == 1) /* SIGTERM */
823 {
824 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
825 --sig_raised; --sig_urgent;
826 SH_FREE(line);
827 return -1;
828 }
829
830 p = sh_dbIO_getdataent (line, MAX_PATH_STORE+1, filepath, &errflag);
831 if (p != NULL)
832 {
833 if (!sh_hash_is_null_record(&(p->theFile)))
834 hashinsert (tab, p);
835 else
836 sh_hash_remove_unconditional (p->fullpath);
837 ++count;
838 }
839 else
840 break;
841 }
842
843 if (line != NULL)
844 SH_FREE(line);
845
846 /* Always keep db in memory, so we have no open file
847 */
848 sl_close (fd);
849
850 sl_fclose (FIL__, __LINE__, sh_fin_fd);
851 sh_fin_fd = NULL;
852
853 return errflag;
854}
855
856
857static int sh_dbIO_load_db_int(sh_file_t * tab[TABSIZE],
858 const char * filepath, const char * uuid)
859{
860#define FGETS_BUF 16384
861
862 SL_TICKET fd = -1;
863
864 if (uuid)
865 {
866 fd = load_data_from_server(uuid);
867 if (SL_ISERROR(fd))
868 return -1;
869 }
870 else if (!filepath)
871 {
872 char * dbpath = file_path('D', 'R');
873
874 fd = load_data_from_server(NULL);
875
876 if (SL_ISERROR(fd))
877 {
878 if (*dbpath == '/')
879 fd = load_data_from_disk(dbpath);
880 }
881 }
882 else
883 {
884 fd = load_data_from_disk(filepath);
885 }
886
887 if (SL_ISERROR(fd))
888 return -1;
889
890 if (sig_termfast == 1) /* SIGTERM */
891 {
892 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
893 --sig_raised; --sig_urgent;
894 aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
895 }
896
897 fd = verify_data(fd);
898 if (SL_ISERROR(fd))
899 return -1;
900
901 if (!uuid) { int i; for (i = 0; i < TABSIZE; ++i) tab[i] = NULL; }
902
903 return read_data (fd, tab, filepath);
904}
905
906
907int sh_dbIO_load_db(sh_file_t * tab[TABSIZE])
908{
909 return sh_dbIO_load_db_int(tab, NULL, NULL);
910}
911int sh_dbIO_load_db_file(sh_file_t * tab[TABSIZE], const char * filepath)
912{
913 return sh_dbIO_load_db_int(tab, filepath, NULL);
914}
915
916int sh_dbIO_load_delta()
917{
918 int status = 0;
919#if defined(SH_WITH_CLIENT)
920 sh_file_t ** mtab = get_default_data_table();
921 int errflag = 0;
922 unsigned int count;
923 time_t last;
924
925 if ( sh.flag.checkSum != SH_CHECK_INIT )
926 {
927 if (sh_hash_get_initialized() != 0)
928 {
929 char * uuid = sh_socket_get_uuid(&errflag, &count, &last);
930
931 if (!uuid)
932 return errflag;
933
934 if (count > 0)
935 sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, count, MSG_E_SUBGEN,
936 _("Retrying download of delta DB"),
937 _("sh_dbIO_load_delta"));
938
939 status = sh_dbIO_load_db_int(mtab, NULL, uuid);
940 if (status < 0)
941 {
942 /* Return status < 0 indicates that max_try is exceeded
943 */
944 if (sh_socket_return_uuid(uuid, count, last) < 0)
945 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_D_DELTAFAIL, uuid);
946 }
947 else
948 {
949 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_D_DELTAOK, uuid);
950 }
951 SH_FREE(uuid);
952 }
953 else
954 {
955 /* not initialized yet */
956 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, -1, MSG_E_SUBGEN,
957 _("Download of delta DB skipped, not initialized yet"),
958 _("sh_dbIO_load_delta"));
959 return -1;
960 }
961 }
962#endif
963 return status;
964}
965
966/******************************************************************
967 *
968 * Writing out a file to the database.
969 *
970 ******************************************************************/
971static int pushdata_isfirst = 1;
972static SL_TICKET pushdata_fd = -1;
973
974static int pushdata_stdout = S_FALSE;
975
976static char * sh_db_version_string = NULL;
977
978int sh_dbIO_writeout_stdout (const char * str)
979{
980 if (!str)
981 { pushdata_stdout = S_TRUE; return 0; }
982 return -1;
983}
984
985int sh_dbIO_version_string(const char * str)
986{
987 if (str)
988 {
989 if (sh_db_version_string != NULL) {
990 SH_FREE(sh_db_version_string);
991 }
992 if (0 == sl_strncmp(str, _("NULL"), 4))
993 {
994 sh_db_version_string = NULL;
995 return 0;
996 }
997 sh_db_version_string = sh_util_strdup(str);
998 return 0;
999 }
1000 return -1;
1001}
1002
1003void do_writeout_checks(const char * outpath)
1004{
1005 if ((pushdata_stdout == S_TRUE) && (sh.flag.update == S_TRUE))
1006 {
1007 dlog(1, FIL__, __LINE__,
1008 _("You cannot write the database to stdout when you use update rather than init.\n"));
1009 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1010 _("Writing database to stdout with update"),
1011 sh.prg_name,
1012 _("sh_dbIO_data_write_int"));
1013 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1014 }
1015
1016 if ((pushdata_stdout == S_TRUE) && (sl_is_suid()))
1017 {
1018 dlog(1, FIL__, __LINE__,
1019 _("You cannot write the database to stdout when running with suid privileges.\n"));
1020 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1021 _("Writing database to stdout when suid"),
1022 sh.prg_name,
1023 _("sh_dbIO_data_write_int"));
1024 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1025 }
1026
1027
1028 if ( (pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) &&
1029 ( (NULL == outpath) || (0 == sl_strcmp(outpath, _("REQ_FROM_SERVER"))) ) )
1030 {
1031 dlog(1, FIL__, __LINE__,
1032 _("You need to configure a local path for initializing the database\nlike ./configure --with-data-file=REQ_FROM_SERVER/some/local/path\n"));
1033 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1034 _("No local path for database specified"),
1035 sh.prg_name,
1036 _("sh_dbIO_data_write_int"));
1037 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1038 }
1039
1040 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE))
1041 {
1042 /* Warn that file already exists; file_path != NULL here because
1043 * checked above
1044 */
1045 struct stat sbuf;
1046
1047 if (0 == retry_lstat(FIL__, __LINE__, outpath, &sbuf))
1048 {
1049 if (sh.flag.update == S_FALSE)
1050 {
1051 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_FI_DBEX,
1052 file_path('D', 'W'));
1053 }
1054 }
1055 }
1056
1057 return;
1058}
1059
1060static SL_TICKET open_writeout_data_truncate(const char * path)
1061{
1062 int status;
1063 SL_TICKET fd;
1064
1065 if ( SL_ISERROR(fd = sl_open_rdwr_trunc(FIL__, __LINE__, path, SL_YESPRIV)))
1066 {
1067 sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_ACCESS,
1068 geteuid(), path);
1069 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1070 }
1071
1072 if (SL_ISERROR(status = sl_lock (fd)))
1073 {
1074 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1075 _("Failed to lock baseline database"), _("sh_dbIO_data_write_int"),
1076 path);
1077 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1078 }
1079 return fd;
1080}
1081
1082static SL_TICKET open_writeout_data(const char * path)
1083{
1084 int status;
1085 SL_TICKET fd;
1086
1087 if ( SL_ISERROR(fd = sl_open_rdwr(FIL__, __LINE__, path, SL_YESPRIV)))
1088 {
1089 sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_ACCESS,
1090 geteuid(), path);
1091 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1092 }
1093
1094 if (SL_ISERROR(status = sl_lock (fd)))
1095 {
1096 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1097 _("Failed to lock baseline database"), _("sh_dbIO_data_write_int"),
1098 path);
1099 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1100 }
1101 return fd;
1102}
1103
1104static void seek_writeout_data(SL_TICKET fd, const char * path)
1105{
1106 int status;
1107
1108 if ( SL_ISERROR(status = sl_forward(fd)))
1109 {
1110 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1111 _("Failed to seek to end of baseline database"),
1112 _("seek_writeout_data"),
1113 path);
1114 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1115 }
1116 return;
1117}
1118
1119static int seek_writeout_data_old(SL_TICKET fd, const char * path)
1120{
1121 char * line = SH_ALLOC(MAX_PATH_STORE+1);
1122
1123 if (SL_ISERROR(sh_dbIO_setdataent_old (fd, line, MAX_PATH_STORE, path)))
1124 {
1125 SH_FREE(line);
1126 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1127 _("Failed to seek to end of baseline database"),
1128 _("seek_writeout_data_old"),
1129 path);
1130 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1131 }
1132 SH_FREE(line);
1133 return 0;
1134}
1135
1136char * prep_path(char * path, int flag)
1137{
1138 size_t old_len = sl_strlen(path);
1139 char * tmp;
1140 size_t tmp_len;
1141 size_t path_len;
1142 char * outpath = NULL;
1143#if !defined(SH_STEALTH)
1144 (void) flag;
1145#endif
1146
1147#if defined(SH_STEALTH)
1148 if (flag == S_TRUE)
1149 sh_do_encode(path, old_len);
1150#endif
1151 tmp = quote_string(path, old_len);
1152 tmp_len = sl_strlen(tmp);
1153#if defined(SH_STEALTH)
1154 if (flag == S_TRUE)
1155 sh_do_decode(path, old_len);
1156#endif
1157
1158 if (tmp && tmp_len <= MAX_PATH_STORE)
1159 {
1160 outpath = sh_util_strdup(path);
1161 }
1162 else
1163 {
1164 char hashbuf[KEYBUF_SIZE];
1165
1166 outpath = sh_util_strdup(sh_tiger_hash (path,
1167 TIGER_DATA, old_len,
1168 hashbuf, sizeof(hashbuf)));
1169 }
1170 if (tmp)
1171 SH_FREE(tmp);
1172
1173 path_len = sl_strlen(outpath);
1174#if defined(SH_STEALTH)
1175 if (flag == S_TRUE)
1176 sh_do_encode(outpath, path_len);
1177#endif
1178
1179 tmp = quote_string(outpath, path_len);
1180 if (tmp) {
1181 SH_FREE(outpath);
1182 outpath = tmp;
1183 }
1184 return outpath;
1185}
1186
1187static char * prep_attr(char * attr_str)
1188{
1189 char * tmp;
1190 char * outstr = NULL;
1191 size_t old_len = sl_strlen(attr_str);
1192
1193#if defined(SH_STEALTH)
1194 sh_do_encode(attr_str, old_len);
1195#endif
1196
1197 tmp = quote_string(attr_str, old_len);
1198 if (tmp)
1199 {
1200 outstr = tmp;
1201 }
1202
1203#if defined(SH_STEALTH)
1204 sh_do_decode(attr_str, old_len);
1205#endif
1206 return outstr;
1207}
1208
1209static void prep_encode(sh_filestore_t * p)
1210{
1211#if defined(SH_STEALTH)
1212 sh_do_encode(p->c_mode, sl_strlen(p->c_mode));
1213 sh_do_encode(p->c_owner, sl_strlen(p->c_owner));
1214 sh_do_encode(p->c_group, sl_strlen(p->c_group));
1215 sh_do_encode(p->checksum, sl_strlen(p->checksum));
1216 sh_do_encode(p->c_attributes, sl_strlen(p->c_attributes));
1217#else
1218 (void) p;
1219#endif
1220 return;
1221}
1222
1223static void prep_struct(sh_filestore_t * p, file_type * buf, char * fileHash)
1224{
1225#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
1226 int i;
1227#endif
1228 p->mark = REC_MAGIC;
1229 sl_strlcpy(p->c_mode, buf->c_mode, CMODE_SIZE);
1230 sl_strlcpy(p->c_group, buf->c_group, GROUP_MAX+1);
1231 sl_strlcpy(p->c_owner, buf->c_owner, USER_MAX+1);
1232 if (fileHash) {
1233 sl_strlcpy(p->checksum, fileHash, KEY_LEN+1);
1234 }
1235#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1236 sl_strlcpy(p->c_attributes, buf->c_attributes, ATTRBUF_SIZE);
1237#else
1238 for (i = 0; i < ATTRBUF_USED; ++i) p->c_attributes[i] = '-';
1239 p->c_attributes[ATTRBUF_USED] = '\0';
1240#endif
1241
1242 prep_encode(p);
1243
1244#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1245 p->attributes = (UINT32) buf->attributes;
1246#else
1247 p->attributes = 0;
1248#endif
1249 p->linkmode = (UINT32) buf->linkmode;
1250 p->hardlinks = (UINT32) buf->hardlinks;
1251 p->dev = (UINT64) buf->dev;
1252 p->rdev = (UINT64) buf->rdev;
1253 p->mode = (UINT32) buf->mode;
1254 p->ino = (UINT32) buf->ino;
1255 p->size = (UINT64) buf->size;
1256 p->mtime = (UINT64) buf->mtime;
1257 p->atime = (UINT64) buf->atime;
1258 p->ctime = (UINT64) buf->ctime;
1259 p->owner = (UINT32) buf->owner;
1260 p->group = (UINT32) buf->group;
1261
1262 p->checkflags = (UINT32) buf->check_flags;
1263
1264 return;
1265}
1266
1267
1268static void write_start_header(SL_TICKET fd)
1269{
1270 char timestring[81];
1271
1272 if (pushdata_stdout == S_FALSE)
1273 {
1274 sl_write (fd, _("\n#Host "), 7);
1275 sl_write (fd, sh.host.name,
1276 sl_strlen(sh.host.name));
1277 sl_write (fd, _(" Version "), 9);
1278 sl_write (fd, sh_db_version_string,
1279 sl_strlen(sh_db_version_string));
1280 sl_write (fd, _(" Date "), 6);
1281 (void) sh_unix_time(0, timestring, sizeof(timestring));
1282 sl_write (fd, timestring, strlen(timestring));
1283 sl_write (fd, "\n", 1);
1284 }
1285 else
1286 {
1287 printf ("%s",_("\n#Host "));
1288 printf ("%s", sh.host.name);
1289 printf ("%s",_(" Version "));
1290 printf ("%s", sh_db_version_string);
1291 printf ("%s",_(" Date "));
1292 (void) sh_unix_time(0, timestring, sizeof(timestring));
1293 printf ("%s\n", timestring);
1294 }
1295}
1296
1297static void write_start_marker(SL_TICKET fd)
1298{
1299 if (sh_db_version_string != NULL)
1300 {
1301 write_start_header(fd);
1302 }
1303
1304 if (pushdata_stdout == S_FALSE)
1305 {
1306#if defined(SH_STEALTH)
1307 sl_write (fd, "\n", 1);
1308 sl_write_line (fd, N_("[SOF]"), 5);
1309#else
1310 sl_write_line (fd, _("\n[SOF]"), 6);
1311#endif
1312 }
1313 else
1314 {
1315#if defined(SH_STEALTH)
1316 puts (N_("[SOF]"));
1317#else
1318 puts (_("\n[SOF]"));
1319#endif
1320 }
1321}
1322
1323static void write_record(SL_TICKET fd, sh_filestore_t * p,
1324 char * fullpath, char * linkpath, char * attr_string)
1325{
1326 static char ll[2] = { '-', '\0' };
1327 char * lpath;
1328
1329 if (!linkpath || 0 == sl_strlen(linkpath))
1330 lpath = ll;
1331 else
1332 lpath = linkpath;
1333
1334 if (pushdata_stdout == S_FALSE)
1335 {
[491]1336 if (SL_ENONE != sl_write (fd, p, sizeof(sh_filestore_t)))
1337 {
1338 char * tmp = sh_util_safe_name(fullpath);
1339 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1340 _("Failed to write record to baseline database"),
1341 _("write_record"),
1342 tmp);
1343 SH_FREE(tmp);
1344 aud_exit(FIL__, __LINE__, EXIT_FAILURE );
1345 }
1346 if (SL_ENONE != sl_write_line_fast (fd, fullpath, sl_strlen(fullpath)))
1347 {
1348 char * tmp = sh_util_safe_name(fullpath);
1349 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1350 _("Failed to write path to baseline database"),
1351 _("write_record"),
1352 tmp);
1353 SH_FREE(tmp);
1354 aud_exit(FIL__, __LINE__, EXIT_FAILURE );
1355 }
1356 if (SL_ENONE != sl_write_line_fast (fd, lpath, sl_strlen(lpath)))
1357 {
1358 char * tmp = sh_util_safe_name(fullpath);
1359 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1360 _("Failed to write lpath to baseline database"),
1361 _("write_record"),
1362 tmp);
1363 SH_FREE(tmp);
1364 aud_exit(FIL__, __LINE__, EXIT_FAILURE );
1365 }
[481]1366 if (attr_string)
1367 sl_write_line_fast (fd, attr_string, sl_strlen(attr_string));
1368 }
1369 else
1370 {
1371 if (fwrite (p, sizeof(sh_filestore_t), 1, stdout))
1372 {
1373 puts (fullpath);
1374 puts (lpath);
1375 if (attr_string)
1376 puts (attr_string);
1377 }
1378 else
1379 {
1380 perror(_("Error writing database"));
1381 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1382 }
1383 }
1384
1385 SH_FREE(fullpath);
1386 if (linkpath)
1387 SH_FREE(linkpath);
1388 if (attr_string)
1389 SH_FREE(attr_string);
1390
1391 return;
1392}
1393
1394static void sh_dbIO_data_write_int (file_type * buf, char * fileHash,
1395 const char * outpath, int truncate)
1396{
1397 static long p_count = 0;
1398 sh_filestore_t p;
1399 char * fullpath = NULL;
1400 char * linkpath = NULL;
1401 char * attr_string = NULL;
1402
1403 SL_ENTER(_("sh_dbIO_data_write_int"));
1404
1405 do_writeout_checks(outpath);
1406
1407 if (sh.flag.update == S_FALSE)
1408 {
1409 if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
1410 {
1411 if (truncate == S_TRUE)
1412 pushdata_fd = open_writeout_data_truncate(outpath);
1413 else
1414 {
1415 pushdata_fd = open_writeout_data(outpath);
1416 seek_writeout_data(pushdata_fd, outpath);
1417 }
1418 }
1419 }
1420 else /* update == TRUE */
1421 {
1422 if (pushdata_isfirst == 1)
1423 {
1424 TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")));
1425 pushdata_fd = open_writeout_data(outpath);
1426 seek_writeout_data_old(pushdata_fd, outpath);
1427 }
1428 }
1429
1430 if (!buf) {
1431 memset(&p, '\0', sizeof(sh_filestore_t));
1432 }
1433
1434 if (buf != NULL)
1435 {
1436 fullpath = prep_path(buf->fullpath, S_TRUE);
1437 }
1438
1439 /* NOTE: TXT entries are c_mode[0] != 'l' and do not get decoded
1440 */
1441 if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL)
1442 {
1443 if (buf->c_mode[0] == 'l')
1444 linkpath = prep_path(buf->link_path, S_TRUE);
1445 else
1446 linkpath = prep_path(buf->link_path, S_FALSE);
1447 }
1448
1449 if (buf != NULL && buf->attr_string != NULL)
1450 {
1451 attr_string = prep_attr(buf->attr_string);
1452 }
1453
1454 if (buf != NULL)
1455 {
1456 prep_struct(&p, buf, fileHash);
1457 if (attr_string)
1458 p.mark |= REC_FLAGS_ATTR;
1459 swap_data(&p);
1460 }
1461
1462 /* write the start marker
1463 */
1464 if (pushdata_isfirst == 1)
1465 {
1466 if (sh.flag.update == S_FALSE)
1467 write_start_marker(pushdata_fd);
1468 pushdata_isfirst = 0;
1469 }
1470
1471 if (buf && fullpath)
1472 {
1473 write_record(pushdata_fd, &p, fullpath, linkpath, attr_string);
1474 ++p_count;
1475 }
1476
1477 if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
1478 {
1479 if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
1480 {
1481 sl_close (pushdata_fd);
1482 pushdata_fd = -1;
1483 }
1484 }
1485
1486 SL_RET0(_("sh_dbIO_data_write_int"));
1487}
1488
1489SH_MUTEX_STATIC(mutex_writeout,PTHREAD_MUTEX_INITIALIZER);
1490
1491void sh_dbIO_data_write (file_type * buf, char * fileHash)
1492{
1493 SH_MUTEX_LOCK(mutex_writeout);
1494 sh_dbIO_data_write_int (buf, fileHash, file_path('D', 'W'), S_FALSE);
1495 SH_MUTEX_UNLOCK(mutex_writeout);
1496 return;
1497}
1498
1499
1500static int dbIO_writeout(sh_file_t * mtab[TABSIZE], const char * outpath, int truncate)
1501{
1502 sh_file_t * p;
1503 int i;
1504 file_type * f;
1505 char fileHash[KEY_LEN + 1];
1506
1507 SL_ENTER(_("dbIO_writeout"));
1508
1509 SH_MUTEX_LOCK(mutex_writeout);
1510 if (!SL_ISERROR(pushdata_fd))
1511 {
1512 sl_close(pushdata_fd);
1513 pushdata_fd = -1;
1514 }
1515 pushdata_isfirst = 1;
1516
1517
1518 SH_MUTEX_LOCK(mutex_hash);
1519 for (i = 0; i < TABSIZE; ++i)
1520 {
1521 for (p = mtab[i]; p; p = p->next)
1522 {
1523 f = sh_hash_create_ft (p, fileHash);
1524 sh_dbIO_data_write_int (f, fileHash, outpath, (i == 0) ? truncate : S_FALSE);
1525 if (f->attr_string) SH_FREE(f->attr_string);
1526 if (f->link_path) SH_FREE(f->link_path);
1527 SH_FREE(f);
1528 }
1529 }
1530 SH_MUTEX_UNLOCK(mutex_hash);
1531
1532 if (!SL_ISERROR(pushdata_fd))
1533 {
1534 sl_close(pushdata_fd);
1535 pushdata_fd = -1;
1536 }
1537 pushdata_isfirst = 1;
1538 SH_MUTEX_UNLOCK(mutex_writeout);
1539
1540 SL_RETURN (0, _("dbIO_writeout"));
1541}
1542
1543int sh_dbIO_writeout_update()
1544{
1545 sh_file_t ** mtab = get_default_data_table();
1546
1547 if (S_TRUE == file_is_remote())
1548 {
1549 sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN,
1550 _("Baseline database is remote"), _("sh_dbIO_writeout"));
1551 SL_RETURN (1, _("sh_dbIO_writeout_update"));
1552 }
1553
1554 return dbIO_writeout(mtab, file_path('D', 'W'), S_FALSE);
1555}
1556
1557int sh_dbIO_writeout_to_path(const char * path)
1558{
1559 sh_file_t ** mtab = get_default_data_table();
1560 return dbIO_writeout(mtab, path, S_TRUE);
1561}
1562
1563static void dbIO_write_record(sh_file_t * record, SL_TICKET fd)
1564{
1565 sh_filestore_t * p = &(record->theFile);
1566 char * fullpath = NULL;
1567 char * linkpath = NULL;
1568 char * attr_string = NULL;
1569
1570 fullpath = prep_path(record->fullpath, S_TRUE);
1571
1572 /* NOTE: TXT entries are c_mode[0] != 'l' and do not get decoded
1573 */
1574 if (record->linkpath != NULL && 0 != strcmp("-", record->linkpath))
1575 {
1576 if (p->c_mode[0] == 'l')
1577 linkpath = prep_path(record->linkpath, S_TRUE);
1578 else
1579 linkpath = prep_path(record->linkpath, S_FALSE);
1580 }
1581
1582 if (record->attr_string != NULL)
1583 attr_string = prep_attr(record->attr_string);
1584
1585 prep_encode(p);
1586 swap_data(p);
1587
1588 write_record(fd, p, fullpath, linkpath, attr_string);
1589 return;
1590}
1591
1592static void dbIO_write_entry(sh_file_t * p)
1593{
1594 static int is_first = 1;
1595
1596 if (is_first)
1597 {
1598 pushdata_isfirst = 1;
1599 if (!sh.outpath || sh.outpath[0] == '\0')
1600 pushdata_stdout = S_TRUE;
1601 else
1602 pushdata_fd = open_writeout_data_truncate(sh.outpath);
1603 write_start_marker(pushdata_fd);
1604 pushdata_isfirst = 0;
1605 is_first = 0;
1606 }
1607
1608 dbIO_write_record(p, pushdata_fd);
1609
1610}
1611
1612
1613/******************************************************************
1614 *
1615 * Listing the database.
1616 *
1617 ******************************************************************/
1618
1619static int ListBinary = S_FALSE;
1620static char * ListFilter = NULL;
1621
1622int sh_dbIO_list_binary (const char * c)
1623{
1624 (void) c;
1625 ListBinary = S_TRUE;
1626 return 0;
1627}
1628int sh_dbIO_list_filter (const char * c)
1629{
1630 ListFilter = sh_util_strdup(c);
1631 return 0;
1632}
1633
1634#include "zAVLTree.h"
1635
1636static zAVLTree * filter_list = NULL;
1637extern char * rtrim (char * str);
1638
1639#include <ctype.h>
1640static void read_filter()
1641{
1642 int i, n = 0;
1643 size_t len;
1644 char * key;
1645 char * str;
1646 char * line = SH_ALLOC(SH_MAXBUF);
1647 FILE * fd = fopen(ListFilter, "r");
1648
1649 if (!fd)
1650 {
1651 perror(_("read_filter: fopen:"));
1652 _exit(EXIT_FAILURE);
1653 }
1654 do {
1655 i = sh_dbIO_getline (fd, line, SH_MAXBUF);
1656 str = rtrim(line);
1657 while (isspace((int)*str)) ++str;
1658
1659 key = sh_files_parse_input(str, &len);
1660
1661 if (key && *key == '/')
1662 {
1663 zAVL_string_set(&filter_list, key);
1664 ++n;
1665 }
1666 } while (i >= 0);
1667
1668 fclose(fd);
1669 SH_FREE(line);
1670
1671 if (n == 0)
1672 {
1673 fprintf(stderr, _("read_filter: empty file <%s>\n"), ListFilter);
1674 _exit (EXIT_FAILURE);
1675 }
1676 return;
1677}
1678
1679static int check_filter(char * path)
1680{
1681 if (NULL == zAVL_string_get(filter_list, path))
1682 return S_FALSE;
1683 return S_TRUE;
1684}
1685
1686int sh_dbIO_list_db (const char * db_file)
1687{
1688 sh_file_t * p;
1689 SL_TICKET fd;
1690 char * line;
1691 int errflag = 0;
1692 int flag = 0;
1693 char * ListFile = get_list_file();
1694
1695 if (!db_file)
1696 {
1697 fputs(_("ERROR: no database file given\n"), stderr);
1698 _exit(EXIT_FAILURE);
1699 return -1;
1700 }
1701 if (sl_is_suid())
1702 {
1703 fputs(_("ERROR: insufficient privilege\n"), stderr);
1704 _exit (EXIT_FAILURE);
1705 return -1; /* for Mac OSX compiler */
1706 }
1707 if (0 == strcmp(db_file, _("default")))
1708 db_file = file_path('D', 'W');
1709 if (!db_file)
1710 {
1711 fputs(_("ERROR: no filename\n"), stderr);
1712 _exit(EXIT_FAILURE);
1713 return -1;
1714 }
1715
1716 if (ListFilter)
1717 read_filter();
1718
1719 line = SH_ALLOC(MAX_PATH_STORE+2);
1720
1721 if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, db_file, SL_YESPRIV)))
1722 {
1723 fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"),
1724 db_file, fd);
1725 _exit(EXIT_FAILURE);
1726 return -1;
1727 }
1728
1729 /* fast forward to start of data
1730 */
1731 if (0 != sh_dbIO_setdataent(fd, line, MAX_PATH_STORE+1, db_file))
1732 {
1733 fprintf(stderr, _("ERROR: can't find start marker in %s\n"),
1734 db_file);
1735 _exit(EXIT_FAILURE);
1736 return -1;
1737 }
1738
1739 while (1)
1740 {
1741 p = sh_dbIO_getdataent (line, MAX_PATH_STORE+1, db_file, &errflag);
1742 if ((p != NULL) && (p->fullpath[0] == '/'))
1743 {
1744 if (!ListFile)
1745 {
1746 flag = 1;
1747 if (ListFilter && S_FALSE == check_filter(p->fullpath))
1748 continue;
1749 if (ListBinary)
1750 dbIO_write_entry (p);
1751 else
1752 sh_hash_list_db_entry (p);
1753 }
1754 else
1755 {
1756 if (0 != sl_strcmp(ListFile, p->fullpath))
1757 {
1758 continue;
1759 }
1760 flag = 1;
1761 if ('l' != p->theFile.c_mode[0])
1762 {
1763 if (sh_hash_printcontent(p->linkpath) < 0)
1764 {
1765 fputs(_("Error listing file content\n"), stderr);
1766 _exit(EXIT_FAILURE);
1767 return -1;
1768 }
1769 }
1770 else
1771 {
1772 fputs(_("File is a link\n"), stderr);
1773 _exit(EXIT_FAILURE);
1774 return -1;
1775 }
1776 break;
1777 }
1778 }
1779 else if (p == NULL)
1780 {
1781 break;
1782 }
1783 }
1784
1785 if (line != NULL)
1786 SH_FREE(line);
1787 sl_close (fd);
1788
1789 fflush(NULL);
1790
1791 if (flag == 0)
1792 {
1793 fputs(_("File not found.\n"), stderr);
1794 _exit(EXIT_FAILURE);
1795 }
1796 else if (errflag < 0)
1797 {
1798 fputs(_("Error while reading file.\n"), stderr);
1799 _exit(EXIT_FAILURE);
1800 }
1801
1802 _exit(EXIT_SUCCESS);
1803 return 0;
1804}
1805
1806/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
1807#endif
Note: See TracBrowser for help on using the repository browser.