source: trunk/src/sh_err_log.c@ 513

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

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

File size: 31.9 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2000 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 <unistd.h>
26#include <time.h>
27
28#include "samhain.h"
29#include "sh_error.h"
30#include "sh_utils.h"
31#include "sh_tiger.h"
32
33#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
34#include <sys/mman.h>
35#endif
36
37
38#undef FIL__
39#define FIL__ _("sh_err_log.c")
40
41#undef FIX_XML
42#define FIX_XML 1
43
44#define MYSIGLEN (2*KEY_LEN + 32)
45
46typedef struct _sh_log_buf {
47 char signature[KEY_LEN+1];
48 char timestamp[KEY_LEN+1];
49#ifdef SH_USE_XML
50 char sig[MYSIGLEN];
51#endif
52 char * msg;
53} sh_sh_log_buf;
54
55extern struct _errFlags errFlags;
56
57#define CHK_KEY 0
58#define CHK_FIL 1
59#define CHK_NON 2
60
61static int get_key_from_file(char * path, char * keyid, char * key)
62{
63 SL_TICKET fd;
64 char * buf;
65 char * bufc;
66
67 if (path[strlen(path)-1] == '\n')
68 path[strlen(path)-1] = '\0';
69
70 /* open the file, then check it
71 */
72 if ( SL_ISERROR(fd = sl_open_read (FIL__, __LINE__, path, SL_NOPRIV)))
73 {
74 fprintf(stderr, _("Could not open file <%s>\n"), path);
75 _exit (EXIT_FAILURE);
76 }
77
78 buf = SH_ALLOC( (size_t)(SH_BUFSIZE+1));
79 bufc = SH_ALLOC( (size_t)(SH_MAXBUF+1));
80
81 while (1 == 1)
82 {
83 buf[0] = '\0';
84 bufc[0] = '\0';
85
86 /* find start of next key
87 */
88 while (0 != sl_strncmp(buf, _("-----BEGIN LOGKEY-----"),
89 sizeof("-----BEGIN LOGKEY-----")-1))
90 {
91 (void) sh_unix_getline (fd, buf, SH_BUFSIZE);
92 if (buf[0] == '\0')
93 {
94 /* End of file reached, return.
95 */
96 (void) fflush(stdout);
97 (void) sl_close(fd);
98 return -1;
99 }
100 }
101
102 /* read key
103 */
104 (void) sh_unix_getline (fd, buf, SH_BUFSIZE);
105
106 if (0 == sl_strncmp(keyid, &buf[KEY_LEN], strlen(keyid)))
107 {
108 (void) sl_strlcpy(key, buf, KEY_LEN+1);
109 (void) sl_close(fd);
110 return 0;
111 }
112 }
113
114 /*@notreached@*/
115}
116
117static int just_list = S_FALSE;
118
119int sh_error_logverify_mod (const char * s)
120{
121 just_list = S_TRUE;
122 if (s) /* compiler warning (unused var) fix */
123 return 0;
124 else
125 return 0;
126}
127
128int sh_error_logverify (const char * s)
129{
130 SL_TICKET fd;
131 int len;
132 int status;
133 int count = 0;
134 int start = -1;
135 char * buf;
136 char * bufc;
137#ifdef SH_USE_XML
138 char * ptr;
139 int fixed_xml = S_TRUE;
140 char c_start;
141#endif
142 char signature[64];
143 char key[KEY_LEN+2];
144 char path[KEY_LEN+1];
145 char timestamp[64];
146 char c_cont;
147 int chk_mode = CHK_KEY;
148 char hashbuf[KEYBUF_SIZE];
149
150 sh_error_logoff();
151
152 if (s == NULL || sl_strlen(s) >= PATH_MAX)
153 {
154 fprintf(stderr, _("FAIL: msg=\"Invalid input\", path=\"%s\"\n"), s);
155 _exit (EXIT_FAILURE);
156 }
157
158 /* Open the file, then check it.
159 */
160 if (0 != sl_is_suid())
161 {
162 fprintf(stderr, _("Cannot open file %s in suid mode\n"), s);
163 _exit (EXIT_FAILURE);
164 }
165
166 if ( SL_ISERROR(fd = sl_open_read (FIL__, __LINE__, s, SL_NOPRIV)) )
167 {
168 fprintf(stderr,
169 _("FAIL: msg=\"File not accessible\", error=\"%ld\", path=\"%s\"\n"), fd, s);
170 _exit (EXIT_FAILURE);
171 }
172
173 /* Find space value.
174 */
175 c_cont = ' ';
176#ifdef SH_STEALTH
177 c_cont ^= XOR_CODE;
178#endif
179
180#ifdef SH_USE_XML
181 c_start = '<';
182#ifdef SH_STEALTH
183 c_start ^= XOR_CODE;
184#endif
185#endif
186
187 buf = (char *) SH_ALLOC( 2*SH_MSG_BUF+1 );
188 bufc = (char *) SH_ALLOC( 2*SH_MSG_BUF+1 );
189
190 while (1 == 1)
191 {
192 /* get the log message
193 */
194 if (sh_unix_getline (fd, buf, (2*SH_MSG_BUF)) < 0)
195 break;
196
197 len = (int) sl_strlen(buf);
198
199#ifdef SH_USE_XML
200#ifdef SH_STEALTH
201 if (0 == sl_strncmp (buf, N_("<trail>"), 7))
202#else
203 if (0 == sl_strncmp (buf, _("<trail>"), 7))
204#endif
205#else
206#ifdef SH_STEALTH
207 if (0 == sl_strncmp (buf, N_("[SOF]"), 5))
208#else
209 if (0 == sl_strncmp (buf, _("[SOF]"), 5))
210#endif
211#endif
212 {
213 if (just_list == S_TRUE)
214 {
215#ifdef SH_STEALTH
216 sh_do_decode (buf, sl_strlen(buf));
217#endif
218 fprintf (stdout, _("%s\n"), buf);
219 }
220
221 /* Found start of audit trail, read first line.
222 */
223 start = 1;
224 do {
225 if ( sh_unix_getline (fd, buf, (2*SH_MSG_BUF)) < 0)
226 break;
227 } while (buf[0] == '\0' || buf[0] == '\n');
228 len = (int) sl_strlen(buf);
229
230 if (just_list == S_TRUE)
231 {
232#ifdef SH_STEALTH
233 if (buf[0] != '\n')
234 sh_do_decode (buf, sl_strlen(buf));
235#endif
236 fprintf (stdout, _("%s\n"), buf);
237 start = 0;
238 }
239
240 ++count;
241 }
242 else if (buf[0] == '\n'
243#ifdef SH_USE_XML
244 ||
245#ifdef SH_STEALTH
246 0 == sl_strncmp(buf, N_("</trail>"), 7)
247#else
248 0 == sl_strncmp(buf, _("</trail>"), 7)
249#endif
250#endif
251 )
252 {
253 if (just_list == S_TRUE)
254 {
255#ifdef SH_STEALTH
256 if (buf[0] != '\n')
257 sh_do_decode (buf, sl_strlen(buf));
258#endif
259 fprintf (stdout, _("%s\n"), buf);
260 }
261
262 /* A newline.
263 */
264 ++count;
265 continue;
266 }
267 else if (start == 0)
268 {
269 /* We are inside an audit trail.
270 */
271 ++count;
272 if (just_list == S_TRUE)
273 {
274#ifdef SH_STEALTH
275 sh_do_decode (buf, sl_strlen(buf));
276#endif
277 fprintf (stdout, _("%s\n"), buf);
278 continue;
279 }
280 }
281 else
282 {
283 /* No start-of-file found yet.
284 */
285 continue;
286 }
287
288 if (just_list == S_TRUE)
289 continue;
290
291 /* Check for a continuation line.
292 */
293 while (1 == 1)
294 {
295 do {
296 if ( sh_unix_getline (fd, bufc, (2*SH_MSG_BUF)) < 0)
297 break;
298 } while (bufc[0] == '\0' || bufc[0] == '\n');
299 ++count;
300 if (bufc[0] == c_cont)
301 {
302 /* A continuation line. Add the newline.
303 */
304 (void) sl_strlcat(buf, "\n", 2*SH_MSG_BUF+1);
305 ++len;
306 (void) sl_strlcat(buf, bufc, 2*SH_MSG_BUF+1);
307 len += (int) sl_strlen(bufc);
308 }
309 else
310 {
311 /* No continuation line. Use it as signature.
312 * A48014C05604EF7C9472330E85453E704024943E556163C2
313 */
314#ifdef SH_USE_XML
315#ifdef SH_STEALTH
316 if (bufc[0] == c_start) /* FIX XML */
317#else
318 if (bufc[0] == c_start)
319#endif
320 {
321 (void) sl_strlcpy(signature, &bufc[5], KEY_LEN+1);
322 fixed_xml = S_TRUE;
323 }
324 else
325 {
326 (void) sl_strlcpy(signature, &bufc[4], KEY_LEN+1);
327 fixed_xml = S_FALSE;
328 }
329 if (sl_strlen(bufc) > (KEY_LEN+18))
330 {
331#ifdef SH_STEALTH
332 if (bufc[0] == c_start) /* FIX XML */
333#else
334 if (bufc[0] == c_start)
335#endif
336 (void) sl_strlcpy(timestamp, &bufc[KEY_LEN+5], 64);
337 else
338 (void) sl_strlcpy(timestamp, &bufc[KEY_LEN+4], 64);
339#ifdef SH_STEALTH
340 ptr = strchr(timestamp, c_start);
341#else
342 ptr = strchr(timestamp, c_start);
343#endif
344 if (ptr) *ptr = '\0';
345 }
346 break;
347#else
348 sl_strlcpy(signature, bufc, KEY_LEN+1);
349 if (sl_strlen(bufc) > KEY_LEN)
350 sl_strlcpy(timestamp, &bufc[KEY_LEN], 64);
351 break;
352#endif
353 }
354 }
355
356 /* Get starting key from command line.
357 */
358 if (start == 1)
359 {
360
361 /* Get the timestamp.
362 */
363
364#ifdef SH_STEALTH
365 sh_do_decode (timestamp, sl_strlen(timestamp));
366#endif
367 key[0] = '\0';
368
369 findKey:
370
371 if (chk_mode != CHK_FIL)
372 {
373 /* Ask for the key.
374 */
375 chk_mode = CHK_KEY;
376 fprintf(stdout, _("\nNew audit trail (%s), enter key|keyfile: "),
377 /*@-usedef@*/timestamp/*@+usedef@*/);
378 key[0] = '\0';
379
380 while (strlen(key) < KEY_LEN )
381 {
382 if (key[0] != '\n' && key[0] != '\0')
383 fprintf(stdout, "%s",_("New audit trail, enter key: "));
384 else if (key[0] == '\n')
385 {
386 (void) sl_strlcpy(key,
387 sh_tiger_hash(NULL, TIGER_DATA, 0,
388 hashbuf, sizeof(hashbuf)),
389 KEY_LEN+1);
390 chk_mode = CHK_NON;
391 break;
392 }
393 (void) fflush(stdout);
394 key[0] = '\0';
395 if (NULL != fgets(key, sizeof(key), stdin))
396 {
397 if (key[0] != '\n')
398 {
399 if (key[strlen(key) - 1] == '\n')
400 key[strlen(key) - 1] = '\0';
401 }
402 if (key[0] == '/')
403 {
404 chk_mode = CHK_FIL;
405 (void) sl_strlcpy(path, key, KEY_LEN+1);
406 break;
407 }
408 }
409 }
410 }
411 /* we now have either a key (chk_mode == CHK_NON|CHK_KEY)
412 * or a file (chk_mode == CHK_FIL)
413 */
414 if (chk_mode == CHK_FIL)
415 {
416 fprintf(stdout, _("\nAudit trail (%s), searching file %s\n"),
417 /*@-usedef@*/timestamp, path/*@+usedef@*/);
418 if (-1 == get_key_from_file(path, timestamp, key))
419 {
420 chk_mode = CHK_KEY;
421 fprintf(stdout, "%s",_("Key not found in file\n"));
422 goto findKey;
423 }
424 }
425
426
427 sh_util_encode(key, buf, 1, 'B');
428 start = 0;
429 }
430 else
431 {
432 /* Iterate the key.
433 */
434 (void) sl_strlcpy (key,
435 sh_tiger_hash (key, TIGER_DATA, KEY_LEN,
436 hashbuf, sizeof(hashbuf)),
437 KEY_LEN+1);
438 }
439
440 (void) sl_strlcat ( buf, key, 2*SH_MSG_BUF + 1);
441
442#ifdef SH_STEALTH
443 sh_do_decode (signature, sl_strlen(signature));
444#endif
445
446 status = sl_strncmp (signature,
447 sh_tiger_hash (buf, TIGER_DATA,
448 (unsigned long) sl_strlen(buf),
449 hashbuf, sizeof(hashbuf)),
450 KEY_LEN);
451
452 buf[len] = '\0'; /* do not print out the key */
453#ifdef SH_STEALTH
454 sh_do_decode (buf, sl_strlen(buf));
455#endif
456
457 if (status != 0)
458 {
459#ifdef SH_USE_XML
460 if (chk_mode == CHK_NON)
461 {
462 if (fixed_xml == S_FALSE)
463 fprintf (stdout, _("XFAIL: line=%05d %s/log>\n"),
464 count-1, buf);
465 else
466 fprintf (stdout, _("XFAIL: line=%05d %s</log>\n"),
467 count-1, buf);
468 }
469 else
470 {
471 if (fixed_xml == S_FALSE)
472 fprintf (stdout, _("FAIL: line=%05d %s/log>\n"),
473 count-1, buf);
474 else
475 fprintf (stdout, _("FAIL: line=%05d %s</log>\n"),
476 count-1, buf);
477 }
478#else
479 if (chk_mode == CHK_NON)
480 fprintf (stdout, _("XFAIL: line=%5d %s\n"), count-1, buf);
481 else
482 fprintf (stdout, _("FAIL: line=%5d %s\n"), count-1, buf);
483#endif
484 }
485 else
486 {
487#ifdef SH_USE_XML
488 if (fixed_xml == S_FALSE)
489 fprintf (stdout, _("PASS: line=%05d %s/log>\n"), count-1, buf);
490 else
491 fprintf (stdout, _("PASS: line=%05d %s</log>\n"), count-1, buf);
492#else
493 fprintf (stdout, _("PASS: line=%5d %s\n"), count-1, buf);
494#endif
495 }
496 }
497
498 /* Cleanup and exit.
499 */
500 (void) sl_close (fd);
501 SH_FREE (buf);
502 SH_FREE (bufc);
503 (void) fflush (stdout);
504 _exit (EXIT_SUCCESS);
505
506 /* Make compilers happy.
507 */
508 /*@notreached@*/
509 return 0;
510}
511
512/********************************************************************
513 *
514 * Runtime code
515 *
516 ********************************************************************/
517static
518int sh_log_open (char * inet_peer,
519 char * logfile, int * service_failure, SL_TICKET * fildesc)
520{
521 SL_TICKET fd = -1;
522 long int status;
523 char * tmp = NULL;
524 uid_t uid;
525 size_t len;
526 char * lockfile = NULL;
527
528 SL_ENTER(_("sh_log_open"));
529
530 /* open/create the file, then check it
531 */
532
533 if ( 0 != (status = tf_trust_check (logfile, SL_YESPRIV))
534 && (*service_failure) == 0)
535 {
536 tmp = sh_util_safe_name (logfile);
537 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_TRUST,
538 (long) sh.effective.uid, tmp);
539 }
540
541 if (status == 0)
542 {
543 fd = sl_open_write (FIL__, __LINE__, logfile, SL_YESPRIV);
544 if (SL_ISERROR(fd))
545 {
546 tmp = sh_util_safe_name (logfile);
547 (void) sl_get_euid(&uid);
548 if ((*service_failure) == 0)
549 sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_E_ACCESS,
550 (long) uid, tmp);
551 status = -1;
552 }
553 }
554
555
556 if (status == 0 && inet_peer == NULL )
557 {
558 status = sh_unix_write_lock_file(logfile);
559 if (status < 0)
560 {
561 tmp = sh_util_safe_name (logfile);
562 len = sl_strlen(tmp);
563 if (sl_ok_adds (6, len))
564 len += 6;
565 lockfile = SH_ALLOC(len);
566 (void) sl_strlcpy(lockfile, tmp, len);
567 (void) sl_strlcat(lockfile, _(".lock"), len);
568 (void) sl_get_euid(&uid);
569 if ((*service_failure) == 0)
570 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_LOCKED,
571 (long) uid, tmp, lockfile);
572 status = -1;
573 SH_FREE(lockfile);
574 (void) sl_close(fd);
575 }
576 }
577
578 if (status == 0)
579 {
580 status = sl_forward(fd);
581 if (SL_ISERROR(status))
582 {
583 tmp = sh_util_safe_name (logfile);
584 (void) sl_get_euid(&uid);
585 if ((*service_failure) == 0)
586 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_ACCESS,
587 (long) uid, tmp);
588 status = -1;
589 (void) sl_close(fd);
590 }
591 }
592
593 if (status < 0)
594 {
595 if ((*service_failure) == 0) {
596 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_SRV_FAIL,
597 _("logfile"), tmp);
598 (*service_failure) = 1;
599 }
600 if (tmp)
601 SH_FREE(tmp);
602 SL_RETURN(-1, _("sh_log_open"));
603 }
604
605 *fildesc = fd;
606 *service_failure = 0;
607 SL_RETURN(0, _("sh_log_open"));
608}
609
610typedef struct lfstc {
611 char * logfile;
612 int service_failure;
613 int log_start;
614 char sigkey_old[KEY_LEN+1];
615 char sigkey_new[KEY_LEN+1];
616 char crypto[KEY_LEN+1];
617 struct lfstc * next;
618} open_logfile;
619
620static open_logfile * logfile_list = NULL;
621
622static int flag_sep_log = S_FALSE;
623
624#ifdef SH_WITH_SERVER
625int set_flag_sep_log (const char * str)
626{
627 return sh_util_flagval(str, &flag_sep_log);
628}
629#endif
630
631/*
632 * --- Log error message to log file. ---
633 */
634int sh_log_file (/*@null@*/char *errmsg, /*@null@*/char * inet_peer)
635{
636 int store1;
637 int store2;
638 int store3;
639 int store4;
640 int store5;
641 int store6;
642 int store7;
643 int store8;
644
645 SL_TICKET fd = -1;
646 size_t status;
647 struct _sh_log_buf log_msg;
648
649 char logfile[SH_PATHBUF+SH_MINIBUF+2];
650 open_logfile * current = logfile_list;
651 open_logfile * next = NULL;
652 char * sigkey_new;
653 char * sigkey_old;
654 char * crypto;
655 char hashbuf[KEYBUF_SIZE];
656
657 SL_ENTER(_("sh_log_file"));
658
659 if (errFlags.HaveLog == BAD) /* paranoia */
660 SL_RETURN((-1), _("sh_log_file"));
661
662#ifdef SH_USE_XML
663 if (NULL == errmsg)
664 {
665 while (current != NULL)
666 {
667 /* don't write second EOF mark
668 */
669 if (current->log_start != S_TRUE && sh.flag.islocked == GOOD)
670 {
671 /* Don't use inet_peer == NULL, userwise a lock file will
672 * be created.
673 */
674 (void) sh_log_open ("\0",
675 current->logfile,
676 &(current->service_failure), &fd);
677
678#ifdef SH_STEALTH
679 (void) sl_write_line (fd, N_("</trail>"), 7);
680 (void) sl_write (fd, "\n", 1);
681 (void) sl_sync(fd);
682#else
683 (void) sl_write_line (fd, _("</trail>\n"), 8);
684 (void) sl_sync(fd);
685#endif
686 (void) sl_close(fd);
687 /* sh_unix_rm_lock_file (current->logfile); */
688 }
689 next = current->next;
690 SH_FREE(current->logfile);
691 SH_FREE(current);
692 current = next;
693 }
694 logfile_list = NULL;
695 SL_RETURN( 0, _("sh_log_file"));
696 }
697#else
698 if (NULL == errmsg)
699 {
700 while (current != NULL)
701 {
702 /* sh_unix_rm_lock_file (current->logfile); */
703 next = current->next;
704 SH_FREE(current->logfile);
705 SH_FREE(current);
706 current = next;
707 }
708 logfile_list = NULL;
709 SL_RETURN( 0, _("sh_log_file"));
710 }
711#endif
712
713 (void) sl_strlcpy (logfile, sh.srvlog.name, sizeof(logfile));
714 if (inet_peer != NULL && flag_sep_log == S_TRUE)
715 {
716 (void) sl_strlcat (logfile, ".", sizeof(logfile));
717 (void) sl_strlcat (logfile, inet_peer, sizeof(logfile));
718 }
719
720 if (sh.flag.log_start == S_TRUE)
721 {
722 while (current != NULL)
723 {
724 current->log_start = S_TRUE;
725 current = current->next;
726 }
727 sh.flag.log_start = S_FALSE;
728 current = logfile_list;
729 }
730
731 while (current != NULL)
732 {
733 if (strcmp(logfile, current->logfile) == 0)
734 break;
735 current = current->next;
736 }
737
738 if (current == NULL)
739 {
740 current = SH_ALLOC(sizeof(open_logfile));
741 current->logfile = SH_ALLOC(strlen(logfile) + 1);
742 (void) sl_strlcpy(current->logfile, logfile, strlen(logfile) + 1);
743 current->service_failure = 0;
744 current->log_start = S_TRUE;
745 memset(current->sigkey_old, (int)'\0', KEY_LEN+1);
746 memset(current->sigkey_new, (int)'\0', KEY_LEN+1);
747 memset(current->crypto, (int)'\0', KEY_LEN+1);
748 current->next = logfile_list;
749 logfile_list = current;
750 }
751
752 if (0 != sh_log_open (inet_peer, current->logfile,
753 &(current->service_failure), &fd))
754 {
755 SL_RETURN ((-1), _("sh_log_file"));
756 }
757
758
759 /* --- Allocate storage and mlock it. ---
760 */
761
762 status = sl_strlen (errmsg);
763 if (!sl_ok_adds(status, (2*KEY_LEN)) || !sl_ok_adds((2*KEY_LEN + status),32))
764 {
765 sl_close(fd);
766 SL_RETURN ((-1), _("sh_log_file"));
767 }
768
769 log_msg.msg = (char *) SH_ALLOC ((size_t) (2*KEY_LEN + status + 32));
770
771#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
772 if (skey->mlock_failed == S_FALSE)
773 {
774 if ( (-1) == sh_unix_mlock( FIL__, __LINE__, log_msg.msg,
775 (size_t)(2*KEY_LEN + status + 32) ) )
776 {
777 skey->mlock_failed = S_TRUE;
778#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
779 sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK);
780#endif
781 }
782 }
783#else
784 if (skey->mlock_failed == S_FALSE)
785 {
786 skey->mlock_failed = S_TRUE;
787#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
788 sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK);
789#endif
790 }
791#endif
792
793 /* --- Write the start marker. ---
794 */
795
796 if (current->log_start == S_TRUE)
797 {
798#ifdef SH_USE_XML
799#ifdef SH_STEALTH
800 (void) sl_write (fd, "\n", 1);
801 (void) sl_write_line (fd, N_("<trail>"), 7);
802 (void) sl_sync(fd);
803#else
804 (void) sl_write_line (fd, _("\n<trail>"), 8);
805 (void) sl_sync(fd);
806#endif
807#else
808#ifdef SH_STEALTH
809 (void) sl_write (fd, "\n", 1);
810 (void) sl_write_line (fd, N_("[SOF]"), 5);
811 (void) sl_sync(fd);
812#else
813 (void) sl_write_line (fd, _("\n[SOF]"), 6);
814 (void) sl_sync(fd);
815#endif
816#endif
817 }
818
819 /* reserve KEY_LEN chars at end for key
820 */
821 (void) sl_strlcpy (log_msg.msg, errmsg, (size_t) status+1 );
822
823
824#ifdef SH_USE_XML
825 /* cut the trailing "/>"
826 */
827 if (log_msg.msg[status-2] == '/')
828 {
829#ifdef FIX_XML
830 log_msg.msg[status-2] = ' '; /* ' ' FIX XML */
831 log_msg.msg[status-1] = '>'; /* '>' FIX XML */
832#else
833 log_msg.msg[status-2] = '>'; /* ' ' FIX XML */
834 log_msg.msg[status-1] = '<'; /* '>' FIX XML */
835#endif
836 log_msg.msg[status] = '\0';
837 }
838 else if (status >= 6 && log_msg.msg[status-5] == '/' &&
839 log_msg.msg[status-6] == '<')
840 {
841#ifdef FIX_XML
842 log_msg.msg[status-6] = '\0';
843 status -= 6;
844#else
845 log_msg.msg[status-5] = '\0';
846 status -= 5;
847#endif
848 }
849#endif
850
851
852#ifdef SH_STEALTH
853 sh_do_encode (log_msg.msg, status);
854#endif
855
856 if (flag_sep_log == S_TRUE && inet_peer != NULL)
857 {
858 sigkey_old = current->sigkey_old;
859 sigkey_new = current->sigkey_new;
860 crypto = current->crypto;
861 }
862 else
863 {
864 sigkey_old = skey->sigkey_old;
865 sigkey_new = skey->sigkey_new;
866 crypto = skey->crypt; /* flawfinder: ignore */
867 }
868
869 /* write the signature
870 */
871 if (current->log_start == S_TRUE)
872 {
873 if (sh.real.user[0] == '\0')
874 (void) sh_unix_getUser();
875
876 /* Initialize the key.
877 */
878 (void) sh_util_keyinit(sigkey_old, KEY_LEN+1);
879
880 /* Hash the key to make sure it has the correct format.
881 */
882 (void) sl_strlcpy(sigkey_new,
883 sh_tiger_hash (sigkey_old, TIGER_DATA, KEY_LEN,
884 hashbuf, sizeof(hashbuf)),
885 KEY_LEN+1);
886
887 /* Copy it to 'crypt' for encryption.
888 */
889 (void) sl_strlcpy(crypto, sigkey_new, KEY_LEN+1);
890
891 /* Use message and compiled-in key to encrypt.
892 */
893 BREAKEXIT(sh_util_encode);
894 sh_util_encode(crypto, log_msg.msg, 0, 'B');
895
896 /* Send out the key.
897 */
898 (void) sh_unix_time(0, log_msg.timestamp, KEY_LEN+1);
899
900 store1 = errFlags.loglevel;
901 store2 = errFlags.sysloglevel;
902 store3 = errFlags.printlevel;
903 store4 = errFlags.exportlevel;
904 store5 = errFlags.maillevel;
905 store6 = errFlags.externallevel;
906 store7 = errFlags.databaselevel;
907 store8 = errFlags.preludelevel;
908
909 /* mail the key
910 */
911 errFlags.loglevel = SH_ERR_NOT;
912 errFlags.sysloglevel = SH_ERR_NOT;
913 errFlags.printlevel = SH_ERR_NOT;
914 errFlags.exportlevel = SH_ERR_NOT;
915 errFlags.externallevel = SH_ERR_NOT;
916 errFlags.databaselevel = SH_ERR_NOT;
917 errFlags.preludelevel = SH_ERR_NOT;
918
919 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_KEY_MAIL,
920 sh.prg_name, crypto,
921 crypto, log_msg.timestamp);
922
923 /* send to other allowed channels
924 */
925 errFlags.maillevel = SH_ERR_NOT;
926 /* errFlags.printlevel = store3; */
927 errFlags.exportlevel = store4;
928 errFlags.externallevel = store6;
929 errFlags.databaselevel = store7;
930 errFlags.preludelevel = store8;
931
932 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_KEY,
933 sh.prg_name, crypto);
934
935 /* Cleanup.
936 */
937 errFlags.loglevel = store1;
938 errFlags.sysloglevel = store2;
939 errFlags.printlevel = store3;
940 errFlags.exportlevel = store4;
941 errFlags.maillevel = store5;
942 errFlags.externallevel = store6;
943 errFlags.databaselevel = store7;
944
945
946 memset (crypto, (int) '\0', KEY_LEN);
947 sh.flag.log_start = S_FALSE;
948 current->log_start = S_FALSE;
949 }
950 else
951 {
952 log_msg.timestamp[0] = '\0';
953 (void) sl_strlcpy (sigkey_new,
954 sh_tiger_hash (sigkey_old, TIGER_DATA, KEY_LEN,
955 hashbuf, sizeof(hashbuf)),
956 KEY_LEN+1);
957 }
958
959 /* --- Sign the message with the signature key. ---
960 */
961 sh_tiger_hash (log_msg.msg, TIGER_DATA,
962 (unsigned long)(status + KEY_LEN),
963 (char *) hashbuf, (size_t) sizeof(hashbuf));
964
965 (void) sl_strlcat (log_msg.msg, sigkey_new, (size_t)(status + KEY_LEN + 2));
966 (void) sl_strlcpy (log_msg.signature,
967 sh_tiger_hash (log_msg.msg, (TigerType) TIGER_DATA,
968 (unsigned long)(status + KEY_LEN),
969 hashbuf, sizeof(hashbuf)),
970 KEY_LEN+1);
971 (void) sl_strlcpy (sigkey_old, sigkey_new, KEY_LEN+1);
972
973 /*@-usedef@*/
974#ifdef SH_USE_XML
975 if (log_msg.timestamp[0] != '\0')
976 sl_snprintf(log_msg.sig, sizeof(log_msg.sig),
977#ifdef FIX_XML
978 _("\n<sig>%s%s</sig></log>\n"), /* <sig> FIX XML */
979#else
980 _("\nsig>%s%s</sig></log>\n"), /* <sig> FIX XML */
981#endif
982 log_msg.signature, log_msg.timestamp);
983 else
984 sl_snprintf(log_msg.sig, sizeof(log_msg.sig),
985#ifdef FIX_XML
986 _("\n<sig>%s</sig></log>\n"), /* <sig> FIX XML */
987#else
988 _("\nsig>%s</sig></log>\n"), /* <sig> FIX XML */
989#endif
990 log_msg.signature);
991 /*@+usedef@*/
992
993#ifdef SH_STEALTH
994 /* don't encode the line breaks (0 + last char)
995 */
996 sh_do_encode (&log_msg.sig[1], (sl_strlen(log_msg.sig)-2) );
997#endif
998#else
999#ifdef SH_STEALTH
1000 sh_do_encode (log_msg.signature, KEY_LEN);
1001 sh_do_encode (log_msg.timestamp, sl_strlen(log_msg.timestamp));
1002#endif
1003#endif
1004
1005#ifdef SH_USE_XML
1006 log_msg.msg[status] = '\0';
1007 (void) sl_strlcat (log_msg.msg, log_msg.sig,
1008 (size_t)(status + 2*KEY_LEN + 32));
1009#ifdef SH_STEALTH
1010 if (NULL != sl_strstr(log_msg.msg, N_("EXIT")) &&
1011 NULL == sl_strstr(log_msg.msg, N_("remote_host")))
1012 {
1013 (void) sl_strlcat (log_msg.msg, N_("</trail>"),
1014 (size_t)(status + 2*KEY_LEN + 32));
1015#else
1016 if (NULL != sl_strstr(log_msg.msg, _("msg=\"EXIT\"")) &&
1017 NULL == sl_strstr(log_msg.msg, _("remote_host")))
1018 {
1019 (void) sl_strlcat (log_msg.msg, _("</trail>"),
1020 (size_t)(status + 2*KEY_LEN + 32));
1021#endif
1022
1023 (void) sl_strlcat (log_msg.msg, _("\n"),
1024 (size_t)(status + 2*KEY_LEN + 32));
1025 current->log_start = S_TRUE;
1026 }
1027#else
1028 log_msg.msg[status] = '\0';
1029 (void) sl_strlcat (log_msg.msg, "\n",
1030 (size_t)(status + KEY_LEN + 2));
1031 (void) sl_strlcat (log_msg.msg, log_msg.signature,
1032 (size_t)(status + KEY_LEN + 2));
1033 if (log_msg.timestamp[0] != '\0')
1034 (void) sl_strlcat (log_msg.msg, log_msg.timestamp,
1035 (size_t)(status + 2*KEY_LEN + 2));
1036 (void) sl_strlcat (log_msg.msg, "\n",
1037 (size_t)(status + 2*KEY_LEN + 3));
1038#endif
1039
1040 /* --- Write out the record. ---
1041 */
1042 (void) sl_write (fd, log_msg.msg, (long) strlen(log_msg.msg));
1043 (void) sl_sync (fd);
1044 (void) sl_close (fd);
1045
1046 /* --- Clean up and free record. ---
1047 */
1048 memset (log_msg.msg, (int)'\0', (size_t)(status + 2*KEY_LEN + 32));
1049 memset (log_msg.signature, (int)'\0', KEY_LEN);
1050 (void) sh_unix_munlock (log_msg.msg,
1051 (size_t)(status + 2*KEY_LEN + 32));
1052 SH_FREE(log_msg.msg);
1053
1054 SL_RETURN (0, _("sh_log_file"));
1055}
1056
1057/* >>>>>>>>>>>>>>>>>>>>>>>>>>>> efile <<<<<<<<<<<<<<<<<< */
1058
1059static char * gEfile = NULL;
1060static int gFail = 0;
1061static long gGid = 0;
1062
1063int sh_efile_group(const char * str)
1064{
1065 int fail;
1066 long gid = sh_group_to_gid(str, &fail);
1067
1068 if (fail < 0)
1069 {
1070 return -1;
1071 }
1072 gGid = gid;
1073 return 0;
1074}
1075
1076
1077int sh_efile_path(const char * str)
1078{
1079 if (!str || !strcmp(str, _("none")))
1080 {
1081 if (gEfile)
1082 SH_FREE(gEfile);
1083 gEfile = NULL;
1084 }
1085 else if (str[0] != '/')
1086 {
1087 return -1;
1088 }
1089 else
1090 {
1091 if (gEfile)
1092 SH_FREE(gEfile);
1093 gEfile = sh_util_strdup(str);
1094 }
1095 gFail = 0;
1096 return 0;
1097}
1098
1099/* write lock for filename
1100 */
1101static int sh_efile_lock (char * filename, int flag)
1102{
1103 extern int get_the_fd (SL_TICKET ticket);
1104 size_t len;
1105 int res = -1;
1106 char myPid[64];
1107 SL_TICKET fd;
1108 char * lockfile;
1109 int status;
1110
1111 sprintf (myPid, "%ld\n", (long) sh.pid); /* known to fit */
1112
1113 if (filename == NULL)
1114 return res;
1115
1116 len = sl_strlen(filename);
1117 if (sl_ok_adds(len, 6))
1118 len += 6;
1119 lockfile = SH_ALLOC(len);
1120 sl_strlcpy(lockfile, filename, len);
1121 sl_strlcat(lockfile, _(".lock"), len);
1122
1123 if ( 0 != (status = tf_trust_check (lockfile, SL_YESPRIV))
1124 && gFail == 0)
1125 {
1126 char * tmp = sh_util_safe_name (lockfile);
1127 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_TRUST,
1128 (long) sh.effective.uid, tmp);
1129 ++gFail;
1130 SH_FREE(tmp);
1131 }
1132
1133 if (status == 0)
1134 {
1135 if (flag == 0)
1136 {
1137 /* --- Delete the lock file. ---
1138 */
1139 res = retry_aud_unlink (FIL__, __LINE__, lockfile);
1140 }
1141 else
1142 {
1143 unsigned int count = 0;
1144
1145 /* fails if file exists
1146 */
1147 do {
1148 fd = sl_open_safe_rdwr (FIL__, __LINE__,
1149 lockfile, SL_YESPRIV);
1150 if (SL_ISERROR(fd))
1151 {
1152 retry_msleep(0, 100);
1153 ++count;
1154 }
1155
1156 } while (SL_ISERROR(fd) && count < 3);
1157
1158 if (!SL_ISERROR(fd))
1159 {
1160 int filed;
1161
1162 res = sl_write (fd, myPid, sl_strlen(myPid));
1163 filed = get_the_fd(fd);
1164 fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
1165 sl_close (fd);
1166 }
1167 else
1168 {
1169 static int nFail = 0;
1170
1171 if (nFail == 0)
1172 {
1173 char errmsg[1024];
1174 char * tmp = sh_util_safe_name (lockfile);
1175
1176 sl_snprintf(errmsg, sizeof(errmsg),
1177 _("Error creating lockfile %s"),
1178 tmp);
1179
1180 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1181 0, MSG_E_SUBGEN,
1182 errmsg, _("sh_efile_lock"));
1183 ++nFail;
1184 SH_FREE(tmp);
1185 }
1186 }
1187 }
1188 }
1189
1190 SH_FREE(lockfile);
1191 return res;
1192}
1193
1194static size_t gSave[6] = { 0 };
1195
1196static void sh_efile_clear()
1197{
1198 int i;
1199
1200 for (i = 0; i < 6; ++i)
1201 gSave[i] = 0;
1202 return;
1203}
1204
1205static void sh_efile_load(size_t * tmp)
1206{
1207 int i;
1208
1209 if (S_TRUE == sl_ok_adds (gSave[0], sh.statistics.bytes_hashed))
1210 gSave[0] += sh.statistics.bytes_hashed;
1211 if (S_TRUE == sl_ok_adds (gSave[1], sh.statistics.dirs_checked))
1212 gSave[1] += sh.statistics.dirs_checked;
1213 if (S_TRUE == sl_ok_adds (gSave[2], sh.statistics.files_checked))
1214 gSave[2] += sh.statistics.files_checked;
1215 if (S_TRUE == sl_ok_adds (gSave[3], sh.statistics.files_report))
1216 gSave[3] += sh.statistics.files_report;
1217 if (S_TRUE == sl_ok_adds (gSave[4], sh.statistics.files_error))
1218 gSave[4] += sh.statistics.files_error;
1219 if (S_TRUE == sl_ok_adds (gSave[5], sh.statistics.files_nodir))
1220 gSave[5] += sh.statistics.files_nodir;
1221
1222 for (i = 0; i < 6; ++i)
1223 tmp[i] = gSave[i];
1224 return;
1225}
1226
1227void sh_efile_report()
1228{
1229 extern int get_the_fd (SL_TICKET ticket);
1230 SL_TICKET fd;
1231 char *efile;
1232 int status = -1;
1233
1234 if (gEfile)
1235 {
1236 size_t tmp[6];
1237
1238 sh_efile_load(tmp);
1239
1240 efile = sh_util_strdup(gEfile);
1241
1242 if (sh_efile_lock (efile, 1) < 0)
1243 goto end;
1244
1245 if ( 0 != (status = tf_trust_check (efile, SL_YESPRIV))
1246 && gFail == 0)
1247 {
1248 char * tmp = sh_util_safe_name (efile);
1249 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_TRUST,
1250 (long) sh.effective.uid, tmp);
1251 ++gFail;
1252 SH_FREE(tmp);
1253 }
1254
1255 if (status == 0)
1256 {
1257 fd = sl_open_write (FIL__, __LINE__, efile, SL_YESPRIV);
1258
1259 if (!SL_ISERROR(fd))
1260 {
1261 char report[511];
1262 char tstamp[TIM_MAX];
1263
1264 time_t now = time(NULL);
1265 int filed = get_the_fd(fd);
1266
1267 (void) sh_unix_time (now, tstamp, sizeof(tstamp));
1268#ifdef HAVE_LONG_LONG
1269 sl_snprintf(report, sizeof(report),
1270 _("%s %lld %ld %ld %ld %ld %ld %ld\n"),
1271 tstamp,
1272 (long long) now,
1273 (long) tmp[0], (long) tmp[1], (long) tmp[2],
1274 (long) tmp[3], (long) tmp[4], (long) tmp[5]);
1275#else
1276 sl_snprintf(report, sizeof(report),
1277 _("%s %ld %ld %ld %ld %ld %ld %ld\n"),
1278 tstamp,
1279 (long) now,
1280 (long) tmp[0], (long) tmp[1], (long) tmp[2],
1281 (long) tmp[3], (long) tmp[4], (long) tmp[5]);
1282#endif
1283
1284 status = sl_forward(fd);
1285 if (!SL_ISERROR(status))
1286 status = sl_write (fd, report, strlen(report));
1287 (void) sl_sync(fd);
1288
1289 /* make group writeable, such that nagios can truncate */
1290 fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
1291 status = fchown (filed, -1, gGid);
1292 if (status < 0)
1293 {
1294 int errnum = errno;
1295 static int nFail = 0;
1296 if (nFail == 0)
1297 {
1298 char errmsg[1024];
1299 char buf[256];
1300 char * tmp = sh_util_safe_name (efile);
1301
1302 sl_snprintf(errmsg, sizeof(errmsg),
1303 _("Error changing group of %s to %ld: %s"),
1304 tmp, gGid,
1305 sh_error_message (errnum, buf, sizeof(buf)));
1306 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1307 errnum, MSG_E_SUBGEN,
1308 errmsg, _("sh_efile_report"));
1309 ++nFail;
1310 SH_FREE(tmp);
1311 }
1312 }
1313
1314 (void) sl_close(fd);
1315 }
1316 else
1317 {
1318 status = -1;
1319 }
1320 }
1321
1322 (void) sh_efile_lock (efile, 0);
1323 end:
1324 SH_FREE(efile);
1325
1326 if (!SL_ISERROR(status))
1327 {
1328 sh_efile_clear();
1329 }
1330 }
1331 return;
1332}
Note: See TracBrowser for help on using the repository browser.