source: trunk/src/sh_err_log.c@ 416

Last change on this file since 416 was 410, checked in by katerina, 12 years ago

Improvements for ticket #303 (option SetReportFile for writing out summary after file check).

File size: 31.9 KB
RevLine 
[1]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>
[405]26#include <time.h>
[1]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 */
[248]72 if ( SL_ISERROR(fd = sl_open_read (FIL__, __LINE__, path, SL_NOPRIV)))
[1]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
[20]119int sh_error_logverify_mod (const char * s)
[1]120{
121 just_list = S_TRUE;
122 if (s) /* compiler warning (unused var) fix */
123 return 0;
124 else
125 return 0;
126}
127
[20]128int sh_error_logverify (const char * s)
[1]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;
[133]148 char hashbuf[KEYBUF_SIZE];
[1]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
[248]166 if ( SL_ISERROR(fd = sl_open_read (FIL__, __LINE__, s, SL_NOPRIV)) )
[1]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
[170]187 buf = (char *) SH_ALLOC( 2*SH_MSG_BUF+1 );
188 bufc = (char *) SH_ALLOC( 2*SH_MSG_BUF+1 );
[1]189
190 while (1 == 1)
191 {
192 /* get the log message
193 */
[170]194 if (sh_unix_getline (fd, buf, (2*SH_MSG_BUF)) < 0)
[1]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 {
[170]225 if ( sh_unix_getline (fd, buf, (2*SH_MSG_BUF)) < 0)
[1]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 {
[170]296 if ( sh_unix_getline (fd, bufc, (2*SH_MSG_BUF)) < 0)
[1]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 */
[170]304 (void) sl_strlcat(buf, "\n", 2*SH_MSG_BUF+1);
[1]305 ++len;
[170]306 (void) sl_strlcat(buf, bufc, 2*SH_MSG_BUF+1);
[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
[279]380 while (strlen(key) < KEY_LEN )
[1]381 {
382 if (key[0] != '\n' && key[0] != '\0')
[210]383 fprintf(stdout, "%s",_("New audit trail, enter key: "));
[1]384 else if (key[0] == '\n')
385 {
386 (void) sl_strlcpy(key,
[133]387 sh_tiger_hash(NULL, TIGER_DATA, 0,
388 hashbuf, sizeof(hashbuf)),
[1]389 KEY_LEN+1);
390 chk_mode = CHK_NON;
391 break;
392 }
393 (void) fflush(stdout);
394 key[0] = '\0';
[153]395 if (NULL != fgets(key, sizeof(key), stdin))
[1]396 {
[153]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 }
[1]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;
[210]421 fprintf(stdout, "%s",_("Key not found in file\n"));
[1]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,
[133]435 sh_tiger_hash (key, TIGER_DATA, KEY_LEN,
436 hashbuf, sizeof(hashbuf)),
[1]437 KEY_LEN+1);
438 }
439
[170]440 (void) sl_strlcat ( buf, key, 2*SH_MSG_BUF + 1);
[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,
[133]448 (unsigned long) sl_strlen(buf),
449 hashbuf, sizeof(hashbuf)),
[1]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 {
[248]543 fd = sl_open_write (FIL__, __LINE__, logfile, SL_YESPRIV);
[1]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);
[34]562 len = sl_strlen(tmp);
563 if (sl_ok_adds (6, len))
564 len += 6;
[1]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 SH_FREE(tmp);
601 SL_RETURN(-1, _("sh_log_open"));
602 }
603
604 *fildesc = fd;
605 *service_failure = 0;
606 SL_RETURN(0, _("sh_log_open"));
607}
608
609typedef struct lfstc {
610 char * logfile;
611 int service_failure;
612 int log_start;
613 char sigkey_old[KEY_LEN+1];
614 char sigkey_new[KEY_LEN+1];
[22]615 char crypto[KEY_LEN+1];
[1]616 struct lfstc * next;
617} open_logfile;
618
619static open_logfile * logfile_list = NULL;
620
621static int flag_sep_log = S_FALSE;
622
623#ifdef SH_WITH_SERVER
[22]624int set_flag_sep_log (const char * str)
[1]625{
626 return sh_util_flagval(str, &flag_sep_log);
627}
628#endif
629
630/*
631 * --- Log error message to log file. ---
632 */
633int sh_log_file (/*@null@*/char *errmsg, /*@null@*/char * inet_peer)
634{
635 int store1;
636 int store2;
637 int store3;
638 int store4;
639 int store5;
640 int store6;
641 int store7;
642 int store8;
643
644 SL_TICKET fd = -1;
[34]645 size_t status;
[1]646 struct _sh_log_buf log_msg;
647
648 char logfile[SH_PATHBUF+SH_MINIBUF+2];
649 open_logfile * current = logfile_list;
650 open_logfile * next = NULL;
651 char * sigkey_new;
652 char * sigkey_old;
[22]653 char * crypto;
[137]654 char hashbuf[KEYBUF_SIZE];
[1]655
656 SL_ENTER(_("sh_log_file"));
657
658 if (errFlags.HaveLog == BAD) /* paranoia */
659 SL_RETURN((-1), _("sh_log_file"));
660
661#ifdef SH_USE_XML
662 if (NULL == errmsg)
663 {
664 while (current != NULL)
665 {
666 /* don't write second EOF mark
667 */
[212]668 if (current->log_start != S_TRUE && sh.flag.islocked == GOOD)
[1]669 {
670 /* Don't use inet_peer == NULL, userwise a lock file will
671 * be created.
672 */
673 (void) sh_log_open ("\0",
674 current->logfile,
675 &(current->service_failure), &fd);
676
677#ifdef SH_STEALTH
678 (void) sl_write_line (fd, N_("</trail>"), 7);
679 (void) sl_write (fd, "\n", 1);
680 (void) sl_sync(fd);
681#else
682 (void) sl_write_line (fd, _("</trail>\n"), 8);
683 (void) sl_sync(fd);
684#endif
685 (void) sl_close(fd);
686 /* sh_unix_rm_lock_file (current->logfile); */
687 }
688 next = current->next;
689 SH_FREE(current->logfile);
690 SH_FREE(current);
691 current = next;
692 }
693 logfile_list = NULL;
694 SL_RETURN( 0, _("sh_log_file"));
695 }
696#else
697 if (NULL == errmsg)
698 {
699 while (current != NULL)
700 {
701 /* sh_unix_rm_lock_file (current->logfile); */
702 next = current->next;
703 SH_FREE(current->logfile);
704 SH_FREE(current);
705 current = next;
706 }
707 logfile_list = NULL;
708 SL_RETURN( 0, _("sh_log_file"));
709 }
710#endif
711
712 (void) sl_strlcpy (logfile, sh.srvlog.name, sizeof(logfile));
713 if (inet_peer != NULL && flag_sep_log == S_TRUE)
714 {
715 (void) sl_strlcat (logfile, ".", sizeof(logfile));
716 (void) sl_strlcat (logfile, inet_peer, sizeof(logfile));
717 }
718
719 if (sh.flag.log_start == S_TRUE)
720 {
721 while (current != NULL)
722 {
723 current->log_start = S_TRUE;
724 current = current->next;
725 }
726 sh.flag.log_start = S_FALSE;
727 current = logfile_list;
728 }
729
730 while (current != NULL)
731 {
732 if (strcmp(logfile, current->logfile) == 0)
733 break;
734 current = current->next;
735 }
736
737 if (current == NULL)
738 {
739 current = SH_ALLOC(sizeof(open_logfile));
740 current->logfile = SH_ALLOC(strlen(logfile) + 1);
741 (void) sl_strlcpy(current->logfile, logfile, strlen(logfile) + 1);
742 current->service_failure = 0;
743 current->log_start = S_TRUE;
744 memset(current->sigkey_old, (int)'\0', KEY_LEN+1);
745 memset(current->sigkey_new, (int)'\0', KEY_LEN+1);
[22]746 memset(current->crypto, (int)'\0', KEY_LEN+1);
[1]747 current->next = logfile_list;
748 logfile_list = current;
749 }
750
751 if (0 != sh_log_open (inet_peer, current->logfile,
752 &(current->service_failure), &fd))
753 {
754 SL_RETURN ((-1), _("sh_log_file"));
755 }
756
757
758 /* --- Allocate storage and mlock it. ---
759 */
760
[34]761 status = sl_strlen (errmsg);
762 if (!sl_ok_adds(status, (2*KEY_LEN)) || !sl_ok_adds((2*KEY_LEN + status),32))
763 {
[248]764 sl_close(fd);
[34]765 SL_RETURN ((-1), _("sh_log_file"));
766 }
767
[1]768 log_msg.msg = (char *) SH_ALLOC ((size_t) (2*KEY_LEN + status + 32));
769
770#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
771 if (skey->mlock_failed == SL_FALSE)
772 {
[19]773 if ( (-1) == sh_unix_mlock( FIL__, __LINE__, log_msg.msg,
[1]774 (size_t)(2*KEY_LEN + status + 32) ) )
775 {
776 skey->mlock_failed = SL_TRUE;
777#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
778 sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK);
779#endif
780 }
781 }
782#else
783 if (skey->mlock_failed == SL_FALSE)
784 {
785 skey->mlock_failed = SL_TRUE;
786#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
787 sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK);
788#endif
789 }
790#endif
791
792 /* --- Write the start marker. ---
793 */
794
795 if (current->log_start == S_TRUE)
796 {
797#ifdef SH_USE_XML
798#ifdef SH_STEALTH
799 (void) sl_write (fd, "\n", 1);
800 (void) sl_write_line (fd, N_("<trail>"), 7);
801 (void) sl_sync(fd);
802#else
803 (void) sl_write_line (fd, _("\n<trail>"), 8);
804 (void) sl_sync(fd);
805#endif
806#else
807#ifdef SH_STEALTH
808 (void) sl_write (fd, "\n", 1);
809 (void) sl_write_line (fd, N_("[SOF]"), 5);
810 (void) sl_sync(fd);
811#else
812 (void) sl_write_line (fd, _("\n[SOF]"), 6);
813 (void) sl_sync(fd);
814#endif
815#endif
816 }
817
818 /* reserve KEY_LEN chars at end for key
819 */
820 (void) sl_strlcpy (log_msg.msg, errmsg, (size_t) status+1 );
821
822
823#ifdef SH_USE_XML
824 /* cut the trailing "/>"
825 */
826 if (log_msg.msg[status-2] == '/')
827 {
828#ifdef FIX_XML
829 log_msg.msg[status-2] = ' '; /* ' ' FIX XML */
830 log_msg.msg[status-1] = '>'; /* '>' FIX XML */
831#else
832 log_msg.msg[status-2] = '>'; /* ' ' FIX XML */
833 log_msg.msg[status-1] = '<'; /* '>' FIX XML */
834#endif
835 log_msg.msg[status] = '\0';
836 }
837 else if (status >= 6 && log_msg.msg[status-5] == '/' &&
838 log_msg.msg[status-6] == '<')
839 {
840#ifdef FIX_XML
841 log_msg.msg[status-6] = '\0';
842 status -= 6;
843#else
844 log_msg.msg[status-5] = '\0';
845 status -= 5;
846#endif
847 }
848#endif
849
850
851#ifdef SH_STEALTH
852 sh_do_encode (log_msg.msg, status);
853#endif
854
855 if (flag_sep_log == S_TRUE && inet_peer != NULL)
856 {
857 sigkey_old = current->sigkey_old;
858 sigkey_new = current->sigkey_new;
[22]859 crypto = current->crypto;
[1]860 }
861 else
862 {
863 sigkey_old = skey->sigkey_old;
864 sigkey_new = skey->sigkey_new;
[22]865 crypto = skey->crypt; /* flawfinder: ignore */
[1]866 }
867
868 /* write the signature
869 */
870 if (current->log_start == S_TRUE)
871 {
872 if (sh.real.user[0] == '\0')
873 (void) sh_unix_getUser();
874
875 /* Initialize the key.
876 */
877 (void) sh_util_keyinit(sigkey_old, KEY_LEN+1);
878
879 /* Hash the key to make sure it has the correct format.
880 */
881 (void) sl_strlcpy(sigkey_new,
[133]882 sh_tiger_hash (sigkey_old, TIGER_DATA, KEY_LEN,
883 hashbuf, sizeof(hashbuf)),
[1]884 KEY_LEN+1);
885
886 /* Copy it to 'crypt' for encryption.
887 */
[22]888 (void) sl_strlcpy(crypto, sigkey_new, KEY_LEN+1);
[1]889
890 /* Use message and compiled-in key to encrypt.
891 */
892 BREAKEXIT(sh_util_encode);
[22]893 sh_util_encode(crypto, log_msg.msg, 0, 'B');
[1]894
895 /* Send out the key.
896 */
[132]897 (void) sh_unix_time(0, log_msg.timestamp, KEY_LEN+1);
[1]898
899 store1 = errFlags.loglevel;
900 store2 = errFlags.sysloglevel;
901 store3 = errFlags.printlevel;
902 store4 = errFlags.exportlevel;
903 store5 = errFlags.maillevel;
904 store6 = errFlags.externallevel;
905 store7 = errFlags.databaselevel;
906 store8 = errFlags.preludelevel;
907
908 /* mail the key
909 */
910 errFlags.loglevel = SH_ERR_NOT;
911 errFlags.sysloglevel = SH_ERR_NOT;
912 errFlags.printlevel = SH_ERR_NOT;
913 errFlags.exportlevel = SH_ERR_NOT;
914 errFlags.externallevel = SH_ERR_NOT;
915 errFlags.databaselevel = SH_ERR_NOT;
916 errFlags.preludelevel = SH_ERR_NOT;
917
918 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_KEY_MAIL,
[22]919 sh.prg_name, crypto,
920 crypto, log_msg.timestamp);
[1]921
922 /* send to other allowed channels
923 */
924 errFlags.maillevel = SH_ERR_NOT;
925 /* errFlags.printlevel = store3; */
926 errFlags.exportlevel = store4;
927 errFlags.externallevel = store6;
928 errFlags.databaselevel = store7;
929 errFlags.preludelevel = store8;
930
931 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_KEY,
[22]932 sh.prg_name, crypto);
[1]933
934 /* Cleanup.
935 */
936 errFlags.loglevel = store1;
937 errFlags.sysloglevel = store2;
938 errFlags.printlevel = store3;
939 errFlags.exportlevel = store4;
940 errFlags.maillevel = store5;
941 errFlags.externallevel = store6;
942 errFlags.databaselevel = store7;
943
944
[22]945 memset (crypto, (int) '\0', KEY_LEN);
[1]946 sh.flag.log_start = S_FALSE;
947 current->log_start = S_FALSE;
948 }
949 else
950 {
951 log_msg.timestamp[0] = '\0';
952 (void) sl_strlcpy (sigkey_new,
[138]953 sh_tiger_hash (sigkey_old, TIGER_DATA, KEY_LEN,
954 hashbuf, sizeof(hashbuf)),
[1]955 KEY_LEN+1);
956 }
957
958 /* --- Sign the message with the signature key. ---
959 */
[137]960 sh_tiger_hash (log_msg.msg, TIGER_DATA,
[138]961 (unsigned long)(status + KEY_LEN),
962 (char *) hashbuf, (size_t) sizeof(hashbuf));
[1]963
964 (void) sl_strlcat (log_msg.msg, sigkey_new, (size_t)(status + KEY_LEN + 2));
965 (void) sl_strlcpy (log_msg.signature,
[137]966 sh_tiger_hash (log_msg.msg, (TigerType) TIGER_DATA,
[138]967 (unsigned long)(status + KEY_LEN),
968 hashbuf, sizeof(hashbuf)),
[1]969 KEY_LEN+1);
970 (void) sl_strlcpy (sigkey_old, sigkey_new, KEY_LEN+1);
971
[22]972 /*@-usedef@*/
[1]973#ifdef SH_USE_XML
974 if (log_msg.timestamp[0] != '\0')
[22]975 sl_snprintf(log_msg.sig, sizeof(log_msg.sig),
[1]976#ifdef FIX_XML
[22]977 _("\n<sig>%s%s</sig></log>\n"), /* <sig> FIX XML */
[1]978#else
[22]979 _("\nsig>%s%s</sig></log>\n"), /* <sig> FIX XML */
[1]980#endif
[22]981 log_msg.signature, log_msg.timestamp);
[1]982 else
[22]983 sl_snprintf(log_msg.sig, sizeof(log_msg.sig),
[1]984#ifdef FIX_XML
[22]985 _("\n<sig>%s</sig></log>\n"), /* <sig> FIX XML */
[1]986#else
[22]987 _("\nsig>%s</sig></log>\n"), /* <sig> FIX XML */
[1]988#endif
[22]989 log_msg.signature);
990 /*@+usedef@*/
[1]991
992#ifdef SH_STEALTH
993 /* don't encode the line breaks (0 + last char)
994 */
995 sh_do_encode (&log_msg.sig[1], (sl_strlen(log_msg.sig)-2) );
996#endif
997#else
998#ifdef SH_STEALTH
999 sh_do_encode (log_msg.signature, KEY_LEN);
1000 sh_do_encode (log_msg.timestamp, sl_strlen(log_msg.timestamp));
1001#endif
1002#endif
1003
1004#ifdef SH_USE_XML
1005 log_msg.msg[status] = '\0';
1006 (void) sl_strlcat (log_msg.msg, log_msg.sig,
1007 (size_t)(status + 2*KEY_LEN + 32));
1008#ifdef SH_STEALTH
1009 if (NULL != sl_strstr(log_msg.msg, N_("EXIT")) &&
1010 NULL == sl_strstr(log_msg.msg, N_("remote_host")))
1011 {
1012 (void) sl_strlcat (log_msg.msg, N_("</trail>"),
1013 (size_t)(status + 2*KEY_LEN + 32));
1014#else
1015 if (NULL != sl_strstr(log_msg.msg, _("msg=\"EXIT\"")) &&
1016 NULL == sl_strstr(log_msg.msg, _("remote_host")))
1017 {
1018 (void) sl_strlcat (log_msg.msg, _("</trail>"),
1019 (size_t)(status + 2*KEY_LEN + 32));
1020#endif
1021
1022 (void) sl_strlcat (log_msg.msg, _("\n"),
1023 (size_t)(status + 2*KEY_LEN + 32));
1024 current->log_start = S_TRUE;
1025 }
1026#else
1027 log_msg.msg[status] = '\0';
1028 (void) sl_strlcat (log_msg.msg, "\n",
1029 (size_t)(status + KEY_LEN + 2));
1030 (void) sl_strlcat (log_msg.msg, log_msg.signature,
1031 (size_t)(status + KEY_LEN + 2));
1032 if (log_msg.timestamp[0] != '\0')
1033 (void) sl_strlcat (log_msg.msg, log_msg.timestamp,
1034 (size_t)(status + 2*KEY_LEN + 2));
1035 (void) sl_strlcat (log_msg.msg, "\n",
1036 (size_t)(status + 2*KEY_LEN + 3));
1037#endif
1038
1039 /* --- Write out the record. ---
1040 */
1041 (void) sl_write (fd, log_msg.msg, (long) strlen(log_msg.msg));
1042 (void) sl_sync (fd);
1043 (void) sl_close (fd);
1044
1045 /* --- Clean up and free record. ---
1046 */
1047 memset (log_msg.msg, (int)'\0', (size_t)(status + 2*KEY_LEN + 32));
1048 memset (log_msg.signature, (int)'\0', KEY_LEN);
1049 (void) sh_unix_munlock (log_msg.msg,
1050 (size_t)(status + 2*KEY_LEN + 32));
1051 SH_FREE(log_msg.msg);
1052
1053 SL_RETURN (0, _("sh_log_file"));
1054}
1055
[405]1056/* >>>>>>>>>>>>>>>>>>>>>>>>>>>> efile <<<<<<<<<<<<<<<<<< */
1057
1058static char * gEfile = NULL;
1059static int gFail = 0;
[410]1060static long gGid = 0;
[405]1061
[410]1062int sh_efile_group(const char * str)
1063{
1064 int fail;
1065 long gid = sh_group_to_gid(str, &fail);
1066
1067 if (fail < 0)
1068 {
1069 return -1;
1070 }
1071 gGid = gid;
1072 return 0;
1073}
1074
1075
[405]1076int sh_efile_path(const char * str)
1077{
1078 if (!str || !strcmp(str, _("none")))
1079 {
1080 if (gEfile)
1081 SH_FREE(gEfile);
1082 gEfile = NULL;
1083 }
1084 else if (str[0] != '/')
1085 {
1086 return -1;
1087 }
1088 else
1089 {
1090 if (gEfile)
1091 SH_FREE(gEfile);
1092 gEfile = sh_util_strdup(str);
1093 }
1094 gFail = 0;
1095 return 0;
1096}
1097
1098/* write lock for filename
1099 */
1100static int sh_efile_lock (char * filename, int flag)
1101{
1102 extern int get_the_fd (SL_TICKET ticket);
1103 size_t len;
1104 int res = -1;
1105 char myPid[64];
1106 SL_TICKET fd;
1107 char * lockfile;
1108 int status;
1109
1110 sprintf (myPid, "%ld\n", (long) sh.pid); /* known to fit */
1111
1112 if (filename == NULL)
1113 return res;
1114
1115 len = sl_strlen(filename);
1116 if (sl_ok_adds(len, 6))
1117 len += 6;
1118 lockfile = SH_ALLOC(len);
1119 sl_strlcpy(lockfile, filename, len);
1120 sl_strlcat(lockfile, _(".lock"), len);
1121
1122 if ( 0 != (status = tf_trust_check (lockfile, SL_YESPRIV))
1123 && gFail == 0)
1124 {
1125 char * tmp = sh_util_safe_name (lockfile);
1126 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_TRUST,
1127 (long) sh.effective.uid, tmp);
1128 ++gFail;
1129 SH_FREE(tmp);
1130 }
1131
1132 if (status == 0)
1133 {
1134 if (flag == 0)
1135 {
1136 /* --- Delete the lock file. ---
1137 */
1138 res = retry_aud_unlink (FIL__, __LINE__, lockfile);
1139 }
1140 else
1141 {
1142 unsigned int count = 0;
1143
1144 /* fails if file exists
1145 */
1146 do {
1147 fd = sl_open_safe_rdwr (FIL__, __LINE__,
1148 lockfile, SL_YESPRIV);
1149 if (SL_ISERROR(fd))
1150 {
1151 retry_msleep(0, 100);
1152 ++count;
1153 }
1154
1155 } while (SL_ISERROR(fd) && count < 3);
1156
1157 if (!SL_ISERROR(fd))
1158 {
1159 int filed;
1160
1161 res = sl_write (fd, myPid, sl_strlen(myPid));
1162 filed = get_the_fd(fd);
1163 fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
1164 sl_close (fd);
1165 }
[410]1166 else
1167 {
1168 static int nFail = 0;
1169
1170 if (nFail == 0)
1171 {
1172 char errmsg[1024];
1173 char * tmp = sh_util_safe_name (lockfile);
1174
1175 sl_snprintf(errmsg, sizeof(errmsg),
1176 _("Error creating lockfile %s"),
1177 tmp);
1178
1179 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1180 0, MSG_E_SUBGEN,
1181 errmsg, _("sh_efile_lock"));
1182 ++nFail;
1183 SH_FREE(tmp);
1184 }
1185 }
[405]1186 }
1187 }
1188
1189 SH_FREE(lockfile);
1190 return res;
1191}
1192
1193static size_t gSave[6] = { 0 };
1194
1195static void sh_efile_clear()
1196{
1197 int i;
1198
1199 for (i = 0; i < 6; ++i)
1200 gSave[i] = 0;
1201 return;
1202}
1203
1204static void sh_efile_load(size_t * tmp)
1205{
1206 int i;
1207
1208 if (SL_TRUE == sl_ok_adds (gSave[0], sh.statistics.bytes_hashed))
1209 gSave[0] += sh.statistics.bytes_hashed;
1210 if (SL_TRUE == sl_ok_adds (gSave[1], sh.statistics.dirs_checked))
1211 gSave[1] += sh.statistics.dirs_checked;
1212 if (SL_TRUE == sl_ok_adds (gSave[2], sh.statistics.files_checked))
1213 gSave[2] += sh.statistics.files_checked;
1214 if (SL_TRUE == sl_ok_adds (gSave[3], sh.statistics.files_report))
1215 gSave[3] += sh.statistics.files_report;
1216 if (SL_TRUE == sl_ok_adds (gSave[4], sh.statistics.files_error))
1217 gSave[4] += sh.statistics.files_error;
1218 if (SL_TRUE == sl_ok_adds (gSave[5], sh.statistics.files_nodir))
1219 gSave[5] += sh.statistics.files_nodir;
1220
1221 for (i = 0; i < 6; ++i)
1222 tmp[i] = gSave[i];
1223 return;
1224}
1225
1226void sh_efile_report()
1227{
[410]1228 extern int get_the_fd (SL_TICKET ticket);
[405]1229 SL_TICKET fd;
1230 char *efile;
1231 int status = -1;
1232
1233 if (gEfile)
1234 {
1235 size_t tmp[6];
1236
1237 sh_efile_load(tmp);
1238
1239 efile = sh_util_strdup(gEfile);
1240
1241 if (sh_efile_lock (efile, 1) < 0)
1242 goto end;
1243
1244 if ( 0 != (status = tf_trust_check (efile, SL_YESPRIV))
1245 && gFail == 0)
1246 {
1247 char * tmp = sh_util_safe_name (efile);
1248 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_TRUST,
1249 (long) sh.effective.uid, tmp);
1250 ++gFail;
1251 SH_FREE(tmp);
1252 }
1253
1254 if (status == 0)
1255 {
1256 fd = sl_open_write (FIL__, __LINE__, efile, SL_YESPRIV);
1257
1258 if (!SL_ISERROR(fd))
1259 {
1260 char report[511];
1261 char tstamp[TIM_MAX];
1262
1263 time_t now = time(NULL);
[410]1264 int filed = get_the_fd(fd);
[405]1265
1266 (void) sh_unix_time (now, tstamp, sizeof(tstamp));
1267#ifdef HAVE_LONG_LONG
1268 sl_snprintf(report, sizeof(report),
1269 _("%s %lld %ld %ld %ld %ld %ld %ld\n"),
1270 tstamp,
1271 (long long) now,
[410]1272 (long) tmp[0], (long) tmp[1], (long) tmp[2],
1273 (long) tmp[3], (long) tmp[4], (long) tmp[5]);
[405]1274#else
1275 sl_snprintf(report, sizeof(report),
1276 _("%s %ld %ld %ld %ld %ld %ld %ld\n"),
1277 tstamp,
1278 (long) now,
[410]1279 (long) tmp[0], (long) tmp[1], (long) tmp[2],
1280 (long) tmp[3], (long) tmp[4], (long) tmp[5]);
[405]1281#endif
1282
1283 status = sl_forward(fd);
1284 if (!SL_ISERROR(status))
1285 status = sl_write (fd, report, strlen(report));
1286 (void) sl_sync(fd);
[410]1287
1288 /* make group writeable, such that nagios can truncate */
1289 fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
1290 status = fchown (filed, -1, gGid);
1291 if (status < 0)
1292 {
1293 int errnum = errno;
1294 static int nFail = 0;
1295 if (nFail == 0)
1296 {
1297 char errmsg[1024];
1298 char buf[256];
1299 char * tmp = sh_util_safe_name (efile);
1300
1301 sl_snprintf(errmsg, sizeof(errmsg),
1302 _("Error changing group of %s to %ld: %s"),
1303 tmp, gGid,
1304 sh_error_message (errnum, buf, sizeof(buf)));
1305 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1306 errnum, MSG_E_SUBGEN,
1307 errmsg, _("sh_efile_report"));
1308 ++nFail;
1309 SH_FREE(tmp);
1310 }
1311 }
1312
[405]1313 (void) sl_close(fd);
1314 }
1315 else
1316 {
1317 status = -1;
1318 }
1319 }
1320
1321 (void) sh_efile_lock (efile, 0);
1322 end:
1323 SH_FREE(efile);
1324
1325 if (!SL_ISERROR(status))
1326 {
1327 sh_efile_clear();
1328 }
1329 }
1330 return;
1331}
Note: See TracBrowser for help on using the repository browser.