source: trunk/src/sh_prelude.c@ 275

Last change on this file since 275 was 227, checked in by katerina, 15 years ago

Fix warnings with -fstack-check

File size: 41.5 KB
Line 
1/*
2 *
3 * Copyright (C) 2005 Yoann Vandoorselaere, Prelude IDS Technologies
4 * Rainer Wichmann
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * 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; see the file COPYING. If not, write to
18 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
22/*
23 * 28/04/2005 : R.W.:
24 * move libprelude 0.8 code to seperate file
25 *
26 * 23/04/2005 : R.W.:
27 * include libprelude 0.9 code from Yoann Vandoorselaere
28 */
29
30
31/*
32 * for strptime()
33 */
34#define _GNU_SOURCE 1
35
36#include "config_xor.h"
37
38#include <stdio.h>
39#include <string.h>
40#include <sys/types.h>
41
42#if TIME_WITH_SYS_TIME
43
44# include <sys/time.h>
45# include <time.h>
46
47#else
48
49# if HAVE_SYS_TIME_H
50# include <sys/time.h>
51# else
52# include <time.h>
53# endif
54
55#endif
56
57#include <unistd.h>
58#include <syslog.h>
59#include <pwd.h>
60
61int sh_argc_store;
62char ** sh_argv_store;
63
64#if defined(HAVE_LIBPRELUDE)
65
66
67/*
68 * _() macros are samhain specific; they are used to replace string
69 * constants at runtime. This is part of the samhain stealth mode
70 * (fill string constants with encoded strings, decode at runtime).
71 */
72#define FIL__ _("sh_prelude.c")
73
74
75#include <libprelude/idmef.h>
76#include <libprelude/prelude.h>
77
78/*
79 * includes for samhain-specific functions (sl_strstr, sh_error_handle)
80 */
81#include "samhain.h"
82#include "sh_cat.h"
83#include "sh_error_min.h"
84#include "sh_prelude.h"
85#define SH_NEED_PWD_GRP 1
86#include "sh_static.h"
87char * sh_util_strdup (const char * str) SH_GNUC_MALLOC;
88/*
89 * When SH_USE_XML is set, value are formated using name="value".
90 * Otherwise, value is formatted using the format name=<value>.
91 */
92#ifdef SH_USE_XML
93# define VALUE_DELIM_START '"'
94# define VALUE_DELIM_END '"'
95#else
96# define VALUE_DELIM_START '<'
97# define VALUE_DELIM_END '>'
98#endif
99
100#define IDMEF_ANALYZER_MODEL _("Samhain")
101#define IDMEF_ANALYZER_CLASS _("Integrity Checker")
102#define IDMEF_ANALYZER_VERSION VERSION
103#define IDMEF_ANALYZER_MANUFACTURER _("http://www.la-samhna.de/samhain/")
104
105
106
107/*
108 * 0 = not initialized; -1 = failed; 1 = initialized
109 */
110static int initialized = 0;
111static int ready_for_init = 0;
112
113static char *profile = NULL;
114static prelude_client_t *client = NULL;
115
116static int severity_map[1 + (unsigned int) IDMEF_IMPACT_SEVERITY_HIGH] = {
117 /* 0: unused (?) */ 0,
118 /* 1: INFO */ 0,
119 /* 2: LOW */ SH_ERR_ALL|SH_ERR_INFO,
120 /* 3: MEDIUM */ SH_ERR_NOTICE|SH_ERR_WARN|SH_ERR_STAMP|SH_ERR_ERR,
121 /* 4: HIGH */ SH_ERR_SEVERE|SH_ERR_FATAL
122};
123
124/* returns 0/tiger, 1/sha1, or 2/md5
125 */
126extern int sh_tiger_get_hashtype(void);
127
128static void clear_and_set (int setpos, int flag)
129{
130 unsigned int i;
131 /* clear everywhere, and set at correct position */
132 for (i = 1; i < (1 + (unsigned int) IDMEF_IMPACT_SEVERITY_HIGH); ++i)
133 severity_map[i] &= ~flag;
134 severity_map[setpos] |= flag;
135 return;
136}
137
138static int set_prelude_severity_int (const char * str, int prelude_sev)
139{
140 char * p;
141 char * dup = strdup (str);
142#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
143 char * saveptr;
144#endif
145
146 if (!dup)
147 return -1;
148
149#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
150 p = strtok_r (dup, ", \t", &saveptr);
151#else
152 p = strtok (dup, ", \t");
153#endif
154 if (p) {
155 do {
156 if (0 == strcmp (p, _("alert")))
157 clear_and_set (prelude_sev, SH_ERR_FATAL);
158 else if (0 == strcmp (p, _("crit")))
159 clear_and_set (prelude_sev, SH_ERR_SEVERE);
160 else if (0 == strcmp (p, _("err")))
161 clear_and_set (prelude_sev, SH_ERR_ERR);
162 else if (0 == strcmp (p, _("mark")))
163 clear_and_set (prelude_sev, SH_ERR_STAMP);
164 else if (0 == strcmp (p, _("warn")))
165 clear_and_set (prelude_sev, SH_ERR_WARN);
166 else if (0 == strcmp (p, _("notice")))
167 clear_and_set (prelude_sev, SH_ERR_NOTICE);
168 else if (0 == strcmp (p, _("debug")))
169 clear_and_set (prelude_sev, SH_ERR_ALL);
170 else if (0 == strcmp (p, _("info")))
171 clear_and_set (prelude_sev, SH_ERR_INFO);
172 else {
173 free (dup);
174 return -1;
175 }
176#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
177 p = strtok_r (NULL, ", \t", &saveptr);
178#else
179 p = strtok (NULL, ", \t");
180#endif
181 } while (p);
182 }
183 free(dup);
184 return 0;
185}
186
187int sh_prelude_map_info (const char * str)
188{
189 return (set_prelude_severity_int(str,(int)IDMEF_IMPACT_SEVERITY_INFO));
190}
191int sh_prelude_map_low (const char * str)
192{
193 return (set_prelude_severity_int(str,(int)IDMEF_IMPACT_SEVERITY_LOW));
194}
195int sh_prelude_map_medium (const char * str)
196{
197 return (set_prelude_severity_int(str,(int)IDMEF_IMPACT_SEVERITY_MEDIUM));
198}
199int sh_prelude_map_high (const char * str)
200{
201 return (set_prelude_severity_int(str,(int)IDMEF_IMPACT_SEVERITY_HIGH));
202}
203
204static idmef_impact_severity_t map_severity (int sam_sev)
205{
206 int i;
207 int max = 1 + (unsigned int) IDMEF_IMPACT_SEVERITY_HIGH;
208 idmef_impact_severity_t retval = IDMEF_IMPACT_SEVERITY_MEDIUM;
209
210 for (i = 0; i < max; ++i) {
211 if (severity_map[i] & sam_sev) {
212 retval = (idmef_impact_severity_t) i;
213 }
214 }
215 return retval;
216}
217
218static char *do_get_value(char *ptr, char delim_start, char delim_end)
219{
220 char *ret = NULL;
221
222 ptr = strchr(ptr, delim_start);
223 if ( ! ptr )
224 return NULL;
225
226 ret = ++ptr;
227
228 ptr = strchr(ptr, delim_end);
229 if ( ! ptr )
230 return NULL;
231
232 *ptr = '\0';
233 ret = strdup(ret);
234 *ptr = delim_end;
235
236 return ret;
237}
238
239
240
241static char *get_value(char *msg, const char *toktmp, const char *toksuffix)
242{
243 char *ptr, tok[128];
244
245 snprintf(tok, sizeof(tok), "%s%s=", toktmp, (toksuffix) ? toksuffix : "");
246
247 ptr = strstr(msg, tok);
248 if ( ! ptr )
249 return NULL;
250
251 return do_get_value(ptr, VALUE_DELIM_START, VALUE_DELIM_END);
252}
253
254
255
256static char *get_time_value(char *msg, const char *toktmp, const char *toksuffix)
257{
258
259 char *ret, *ptr, tok[128];
260
261 snprintf(tok, sizeof(tok), "%s%s=", toktmp, (toksuffix) ? toksuffix : "");
262
263 ptr = strstr(msg, tok);
264 if ( ! ptr )
265 return NULL;
266
267#ifndef SH_USE_XML
268 ret = do_get_value(ptr, '[', ']');
269#else
270 ret = do_get_value(ptr, VALUE_DELIM_START, VALUE_DELIM_END);
271#endif
272
273 return ret;
274}
275
276
277
278
279#if 0
280void debug_print_message(idmef_message_t *msg)
281{
282 int ret;
283 prelude_io_t *fd;
284
285 ret = prelude_io_new(&fd);
286 if ( ret < 0 )
287 return;
288
289 prelude_io_set_file_io(fd, stderr);
290 idmef_message_print(idmef, fd);
291
292 prelude_io_destroy(fd);
293}
294#endif
295
296
297
298static int idmef_time_from_samhain(idmef_time_t **time, const char *str)
299{
300 int ret;
301 char *ptr;
302 time_t utc;
303 struct tm lt;
304
305 /*
306 * Samhain stamp are encoded in UTC.
307 */
308 ptr = strptime(str, _("%Y-%m-%dT%H:%M:%S"), &lt);
309 if ( ! ptr ) {
310 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
311 _("could not format Samhain time"), _("idmef_time_from_samhain"));
312 return -1;
313 }
314
315 utc = prelude_timegm(&lt);
316
317 ret = idmef_time_new_from_time(time, &utc);
318 if ( ret < 0 )
319 return ret;
320
321 return 0;
322}
323
324/* flawfinder: ignore *//* is part of name, not access() */
325static void get_access_info(idmef_file_access_t *access, char * mode, int pos, int mpos)
326{
327 int got = 0;
328 int ret;
329 prelude_string_t *str;
330
331 do {
332 if ( mode[pos] == 'r' ) {
333 /* flawfinder: ignore *//* is part of name, not access() */
334 ret = idmef_file_access_new_permission(access, &str, IDMEF_LIST_APPEND);
335 if ( ret < 0 )
336 return;
337 prelude_string_set_dup(str, _("read"));
338 ++got;
339 }
340 else if ( mode[pos] == 'w' ) {
341 /* flawfinder: ignore *//* is part of name, not access() */
342 ret = idmef_file_access_new_permission(access, &str, IDMEF_LIST_APPEND);
343 if ( ret < 0 )
344 return;
345 prelude_string_set_dup(str, _("write"));
346 ++got;
347 }
348 else if ( mode[pos] == 'x' || mode[pos] == 's' || mode[pos] == 't') {
349 /* flawfinder: ignore *//* is part of name, not access() */
350 ret = idmef_file_access_new_permission(access, &str, IDMEF_LIST_APPEND);
351 if ( ret < 0 )
352 return;
353
354 if ( mode[pos] == 'x' && mode[0] == 'd' )
355 prelude_string_set_dup(str, _("search"));
356
357 else if ( mode[pos] == 'x' || mode[pos] == 't' )
358 prelude_string_set_dup(str, _("execute"));
359
360 else /* 's' */
361 prelude_string_set_dup(str, _("executeAs"));
362 ++got;
363 }
364 ++pos;
365 } while (pos <= mpos);
366
367 if ( got == 0 ) {
368 /* flawfinder: ignore *//* is part of name, not access() */
369 ret = idmef_file_access_new_permission(access, &str, IDMEF_LIST_APPEND);
370 if ( ret < 0 )
371 return;
372 prelude_string_set_dup(str, _("noAccess"));
373 }
374 return;
375}
376
377
378static void get_file_infos(idmef_target_t *target, char *msg,
379 idmef_file_category_t category)
380{
381 int ret;
382 int hashtype = 0;
383 char *ptr;
384 idmef_time_t *time;
385 idmef_file_t *file;
386 idmef_inode_t *inode;
387 prelude_string_t *str;
388 idmef_checksum_t *checksum;
389 idmef_file_access_t *access; /* flawfinder: ignore */
390 idmef_user_id_t *userid;
391 const char *suffix = (category == IDMEF_FILE_CATEGORY_CURRENT) ? "_new" : "_old";
392 char *mode = NULL;
393
394 ret = idmef_target_new_file(target, &file, IDMEF_LIST_APPEND);
395 if ( ret < 0 )
396 return;
397 idmef_file_set_category(file, category);
398
399 ptr = get_value(msg, _("path"), NULL);
400 if ( ptr ) {
401 /*
402 * In term of IDMEF, this is the full path,
403 * including the name.
404 */
405 ret = idmef_file_new_path(file, &str);
406 if ( ret < 0 ) {
407 free(ptr);
408 return;
409 }
410 prelude_string_set_nodup(str, ptr);
411
412 ptr = strrchr(ptr, '/');
413 if ( ptr ) {
414 ret = idmef_file_new_name(file, &str);
415 if ( ret == 0 ) {
416 prelude_string_set_dup(str, ptr + 1);
417 }
418 }
419 }
420
421 ptr = get_value(msg, _("size"), suffix);
422 if ( ptr ) {
423 idmef_file_set_data_size(file, strtoul(ptr, NULL, 10));
424 free(ptr);
425 }
426
427 ptr = get_time_value(msg, _("mtime"), suffix);
428 if ( ptr ) {
429 ret = idmef_time_from_samhain(&time, ptr);
430 if ( ret == 0 ) {
431 idmef_file_set_modify_time(file, time);
432 }
433 free(ptr);
434 }
435
436 ptr = get_time_value(msg, _("ctime"), suffix);
437 if ( ptr ) {
438 ret = idmef_time_from_samhain(&time, ptr);
439 if ( ret == 0 ) {
440 idmef_file_set_create_time(file, time);
441 }
442 free(ptr);
443 }
444
445 ptr = get_value(msg, _("inode"), suffix);
446 if ( ptr ) {
447 ret = idmef_file_new_inode(file, &inode);
448 if ( ret == 0 ) {
449 char * dev = get_value(msg, _("dev"), suffix);
450 if (dev) {
451 char * q = strchr(dev, ',');
452 if (*q) {
453 *q = '\0'; ++q;
454 idmef_inode_set_major_device(inode, strtoul(dev, NULL, 0));
455 idmef_inode_set_minor_device(inode, strtoul( q, NULL, 0));
456 }
457 free(dev);
458 }
459 idmef_inode_set_number(inode, strtoul(ptr, NULL, 10));
460 }
461 free(ptr);
462 }
463
464 ptr = get_value(msg, _("chksum"), suffix);
465 if ( ptr ) {
466 ret = idmef_file_new_checksum(file, &checksum, IDMEF_LIST_APPEND);
467 if ( ret < 0 ) {
468 free(ptr);
469 goto get_mode;
470 }
471
472 hashtype = sh_tiger_get_hashtype();
473
474 if (hashtype == 0)
475 idmef_checksum_set_algorithm(checksum, IDMEF_CHECKSUM_ALGORITHM_TIGER);
476
477 else if (hashtype == 1)
478 idmef_checksum_set_algorithm(checksum, IDMEF_CHECKSUM_ALGORITHM_SHA1);
479
480 else if (hashtype == 2)
481 idmef_checksum_set_algorithm(checksum, IDMEF_CHECKSUM_ALGORITHM_MD5);
482
483 else
484 idmef_checksum_set_algorithm(checksum, IDMEF_CHECKSUM_ALGORITHM_TIGER);
485
486
487 ret = idmef_checksum_new_value(checksum, &str);
488 if ( ret < 0 ) {
489 free(ptr);
490 goto get_mode;
491 }
492
493 /* will be freed on destroy()
494 */
495 prelude_string_set_nodup(str, ptr);
496 }
497
498 get_mode:
499
500 mode = get_value(msg, _("mode"), suffix);
501 if ( mode ) {
502 /* flawfinder: ignore *//* is part of name, not access() */
503 ret = idmef_file_new_file_access(file, &access, IDMEF_LIST_APPEND);
504 if ( ret < 0 )
505 goto get_owner;
506
507 /* flawfinder: ignore *//* is part of name, not access() */
508 ret = idmef_file_access_new_user_id(access, &userid);
509 if ( ret < 0 )
510 goto get_owner;
511 idmef_user_id_set_type(userid, IDMEF_USER_ID_TYPE_OTHER_PRIVS);
512
513 /* flawfinder: ignore *//* is part of name, not access() */
514 get_access_info ( access, mode, 7, 9 );
515 }
516
517 get_owner:
518
519 ptr = get_value(msg, _("owner"), suffix);
520 if ( ptr ) {
521 char * uid;
522
523 /* flawfinder: ignore *//* is part of name, not access() */
524 ret = idmef_file_new_file_access(file, &access, IDMEF_LIST_APPEND);
525 if ( ret < 0 ) {
526 free(ptr);
527 goto get_group;
528 }
529
530 /* flawfinder: ignore *//* is part of name, not access() */
531 ret = idmef_file_access_new_user_id(access, &userid);
532 if ( ret < 0 ) {
533 free(ptr);
534 goto get_group;
535 }
536 idmef_user_id_set_type(userid, IDMEF_USER_ID_TYPE_USER_PRIVS);
537
538 ret = idmef_user_id_new_name(userid, &str);
539 if ( ret < 0 ) {
540 free(ptr);
541 goto get_group;
542 }
543 prelude_string_set_nodup(str, ptr);
544
545 uid = get_value(msg, _("iowner"), suffix);
546 if ( ! uid )
547 goto get_group;
548
549 idmef_user_id_set_number(userid, strtoul(uid, NULL, 0));
550
551 if ( mode ) {
552 /* flawfinder: ignore *//* is part of name, not access() */
553 get_access_info ( access, mode, 1, 3 );
554 }
555
556 free(uid);
557 }
558
559 get_group:
560
561 ptr = get_value(msg, _("group"), suffix);
562 if ( ptr ) {
563 char *gid;
564
565 /* flawfinder: ignore *//* is part of name, not access() */
566 ret = idmef_file_new_file_access(file, &access, IDMEF_LIST_APPEND);
567 if ( ret < 0 ) {
568 free(ptr);
569 goto mode_free;
570 }
571
572 ret = idmef_file_access_new_user_id(access, &userid);/* flawfinder: ignore *//* is part of name, not access() */
573 if ( ret < 0 ) {
574 free(ptr);
575 goto mode_free;
576 }
577
578 idmef_user_id_set_type(userid, IDMEF_USER_ID_TYPE_GROUP_PRIVS);
579
580 ret = idmef_user_id_new_name(userid, &str);
581 if ( ret < 0 ) {
582 free(ptr);
583 goto mode_free;
584 }
585
586 prelude_string_set_nodup(str, ptr);
587
588 gid = get_value(msg, _("igroup"), suffix);
589 if ( ! gid )
590 goto mode_free;
591
592 idmef_user_id_set_number(userid, strtoul(gid, NULL, 0));
593
594 if ( mode ) {
595 get_access_info ( access, mode, 4, 6 ); /* flawfinder: ignore */
596 }
597
598 free(gid);
599 }
600
601 mode_free:
602
603 if ( mode ) {
604 free ( mode );
605 }
606
607 return;
608}
609
610
611
612static int map_policy_to_class(char *msg, unsigned long msgid, idmef_impact_t *impact, prelude_string_t *out)
613{
614 char *ptr;
615 int ret, i;
616 struct tbl {
617 unsigned int msgid;
618 const char *name;
619 idmef_impact_type_t type;
620 } tbl[] = {
621
622#ifdef SH_USE_UTMP
623 { MSG_UT_LG1X, N_("User Login"), IDMEF_IMPACT_TYPE_USER },
624 { MSG_UT_LG1A, N_("User Login"), IDMEF_IMPACT_TYPE_USER },
625 { MSG_UT_LG1B, N_("User Login"), IDMEF_IMPACT_TYPE_USER },
626 { MSG_UT_LG2X, N_("Multiple User Login"), IDMEF_IMPACT_TYPE_USER },
627 { MSG_UT_LG2A, N_("Multiple User Login"), IDMEF_IMPACT_TYPE_USER },
628 { MSG_UT_LG2B, N_("Multiple User Login"), IDMEF_IMPACT_TYPE_USER },
629 { MSG_UT_LG3X, N_("User Logout"), IDMEF_IMPACT_TYPE_USER },
630 { MSG_UT_LG3A, N_("User Logout"), IDMEF_IMPACT_TYPE_USER },
631 { MSG_UT_LG3B, N_("User Logout"), IDMEF_IMPACT_TYPE_USER },
632 { MSG_UT_LG3C, N_("User Logout"), IDMEF_IMPACT_TYPE_USER },
633#endif
634
635#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
636 { MSG_FI_MISS, N_("File Missing"), IDMEF_IMPACT_TYPE_FILE },
637 { MSG_FI_MISS2, N_("File Missing"), IDMEF_IMPACT_TYPE_FILE },
638 { MSG_FI_ADD, N_("File Added"), IDMEF_IMPACT_TYPE_FILE },
639 { MSG_FI_ADD2, N_("File Added"), IDMEF_IMPACT_TYPE_FILE },
640 { MSG_FI_CHAN, N_("File Modified"), IDMEF_IMPACT_TYPE_FILE },
641 { MSG_FI_NODIR, N_("File found where directory was expected"), IDMEF_IMPACT_TYPE_FILE },
642#endif
643
644#ifdef SH_USE_KERN
645 { MSG_KERN_POLICY, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER },
646 { MSG_KERN_POL_CO, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER },
647 { MSG_KERN_PROC, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER },
648 { MSG_KERN_GATE, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER },
649 { MSG_KERN_IDT, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER },
650 { MSG_KERN_SYSCALL, N_("Kernel Modified"), IDMEF_IMPACT_TYPE_OTHER },
651#endif
652
653#ifdef SH_USE_PORTCHECK
654 { MSG_PORT_MISS, N_("Service closed"), IDMEF_IMPACT_TYPE_OTHER },
655 { MSG_PORT_NEW, N_("Service opened"), IDMEF_IMPACT_TYPE_OTHER },
656 { MSG_PORT_RESTART, N_("Service restarted"), IDMEF_IMPACT_TYPE_OTHER },
657 { MSG_PORT_NEWPORT, N_("Service restarted"), IDMEF_IMPACT_TYPE_OTHER },
658#endif
659
660#ifdef SH_USE_SUIDCHK
661 { MSG_SUID_POLICY, N_("SUID/SGID File Detected"), IDMEF_IMPACT_TYPE_FILE },
662#endif
663 /*
664 * This must be the last table entry
665 */
666 { 0, NULL, IDMEF_IMPACT_TYPE_OTHER },
667 };
668
669 for ( i = 0; tbl[i].name != NULL; i++ ) {
670 if ( tbl[i].msgid != msgid )
671 continue;
672
673 idmef_impact_set_type(impact, tbl[i].type);
674 return prelude_string_cat(out, _(tbl[i].name));
675 }
676
677 /* some other message
678 */
679 ptr = get_value(msg, _("msg"), NULL);
680 if ( ! ptr ) {
681 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
682 _("could not format Samhain message"), _("map_policy_to_class"));
683 return -1;
684 }
685
686 ret = prelude_string_cat(out, ptr);
687 free(ptr);
688
689 return ret;
690}
691
692
693#ifdef SH_USE_PORTCHECK
694static int get_service_info(char *msg, idmef_alert_t *alert)
695{
696 int ret;
697 long port;
698 char *ptr, *new, *tmp, *ip, *srv, *protocol, *end;
699 prelude_string_t *str;
700 idmef_address_t *address;
701 idmef_node_t *node;
702 idmef_user_t *user;
703 idmef_process_t *process;
704 idmef_service_t *service;
705 idmef_source_t *source = idmef_alert_get_next_source(alert, NULL);
706 struct passwd *pw;
707#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
708 struct passwd pwd;
709 char * buffer;
710#endif
711
712 new = sh_util_strdup(msg);
713
714 ptr = strstr(new, _("port: "));
715 if ( ! ptr ) {
716 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
717 _("malformed Samhain port check message"), _("get_service_info"));
718 SH_FREE( new );
719 return -1;
720 }
721
722 ptr += 6; /* skip 'port: ', position on first byte of interface */
723 tmp = strchr(ptr, ':');
724 if ( ! tmp ) {
725 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
726 _("malformed Samhain port check message (no port)"), _("get_service_info"));
727 SH_FREE( new );
728 return -1;
729 }
730 *tmp = '\0';
731
732 /* Get interface
733 */
734 ip = strdup(ptr);
735 if ( ip ) {
736 if ( ! source ) {
737 ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
738 if ( ret < 0 ) {
739 free(ip);
740 SH_FREE( new );
741 return ret;
742 }
743 }
744
745 ret = idmef_source_new_node(source, &node);
746 if ( ret < 0 ) {
747 free(ip);
748 SH_FREE( new );
749 return ret;
750 }
751
752 ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND);
753 if ( ret < 0 ) {
754 free(ip);
755 SH_FREE( new );
756 return ret;
757 }
758
759 ret = idmef_address_new_address(address, &str);
760 if ( ret < 0 ) {
761 free(ip);
762 SH_FREE( new );
763 return ret;
764 }
765
766 prelude_string_set_nodup(str, ip);
767 }
768
769 ptr = tmp;
770 ++ptr;
771 tmp = strchr(ptr, '/');
772 if ( ! tmp ) {
773 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
774 _("malformed Samhain port check message (no protocol)"), _("get_service_info"));
775 SH_FREE( new );
776 return -1;
777 }
778 *tmp = '\0';
779
780 /* Get port number
781 */
782 port = strtol(ptr, &end, 0);
783 if ( *ptr && *end == '\0' && port >= 0 && port < 65536) {
784
785 char * tmpw;
786
787 if ( ! source ) {
788 ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
789 if ( ret < 0 ) {
790 SH_FREE( new );
791 return ret;
792 }
793 }
794
795 ret = idmef_source_new_service(source, &service);
796 if ( ret < 0 ) {
797 SH_FREE( new );
798 return ret;
799 }
800
801 idmef_service_set_port(service, port);
802
803 ret = idmef_service_new_protocol(service, &str);
804 if ( ret < 0 ) {
805 SH_FREE( new );
806 return ret;
807 }
808
809 ++tmp;
810 if (*tmp) {
811 char * tmpw = tmp;
812 char tmpw_store;
813 while (*tmpw && !isblank((int) *tmpw)) ++tmpw;
814 tmpw_store = *tmpw; *tmpw = '\0';
815 protocol = strdup(tmp);
816 *tmpw = tmpw_store;
817 prelude_string_set_nodup(str, protocol);
818 }
819
820 }
821
822 ptr = tmp;
823 ++ptr;
824 ptr = strchr(ptr, '(');
825 if ( ! ptr ) {
826 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
827 _("malformed Samhain port check message (no service)"), _("get_service_info"));
828 SH_FREE( new );
829 return -1;
830 }
831 ++ptr;
832 tmp = strchr(ptr, ')');
833 if ( ! tmp ) {
834 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
835 _("malformed Samhain port check message (service not closed)"), _("get_service_info"));
836 SH_FREE( new );
837 return -1;
838 }
839 *tmp = '\0';
840
841 /* Get service
842 */
843 srv = strdup(ptr);
844 if ( srv ) {
845 if ( ! source ) {
846 ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
847 if ( ret < 0 ) {
848 free(srv);
849 SH_FREE( new );
850 return ret;
851 }
852 }
853
854 if ( ! service ) {
855 ret = idmef_source_new_service(source, &service);
856 if ( ret < 0 ) {
857 free(srv);
858 SH_FREE( new );
859 return ret;
860 }
861 }
862
863 ret = idmef_service_new_name(service, &str);
864 if ( ret < 0 ) {
865 free(srv);
866 SH_FREE( new );
867 return ret;
868 }
869
870 prelude_string_set_nodup(str, srv);
871 }
872
873 SH_FREE( new );
874
875 ptr = get_value(msg, _("userid"), NULL);
876
877 if ( ptr ) {
878
879 idmef_user_id_t * user_id;
880
881 ret = idmef_source_new_user(source, &user);
882 if ( ret < 0 ) {
883 free(ptr);
884 return ret;
885 }
886
887 idmef_user_set_category(user, IDMEF_USER_CATEGORY_APPLICATION);
888
889 ret = idmef_user_new_user_id(user, &user_id, IDMEF_LIST_APPEND);
890 if ( ret < 0 ) {
891 free(ptr);
892 return ret;
893 }
894
895 idmef_user_id_set_type(user_id, IDMEF_USER_ID_TYPE_CURRENT_USER);
896
897#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
898 buffer = SH_ALLOC(SH_PWBUF_SIZE);
899 sh_getpwnam_r(ptr, &pwd, buffer, SH_PWBUF_SIZE, &pw);
900#else
901 pw = sh_getpwnam(ptr);
902#endif
903 if ( pw )
904 idmef_user_id_set_number(user_id, pw->pw_uid);
905
906 ret = idmef_user_id_new_name(user_id, &str);
907 if ( ret < 0 ) {
908 free(ptr);
909#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
910 SH_FREE(buffer);
911#endif
912 return ret;
913 }
914 prelude_string_set_nodup(str, ptr);
915
916#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
917 SH_FREE(buffer);
918#endif
919 }
920
921
922 ptr = get_value(msg, _("path"), NULL);
923 tmp = get_value(msg, _("pid"), NULL);
924
925 if ( ptr ) {
926
927 /*
928 * In term of IDMEF, this is the full path,
929 * including the name.
930 */
931 ret = idmef_source_new_process(source, &process);
932 if ( ret < 0 ) {
933 free(ptr);
934 return ret;
935 }
936
937 ret = idmef_process_new_path(process, &str);
938 if ( ret < 0 ) {
939 free(ptr);
940 return ret;
941 }
942 prelude_string_set_nodup(str, ptr);
943
944
945 if ( NULL != strrchr(ptr, '/') ) {
946 ret = idmef_process_new_name(process, &str);
947 if ( ret == 0 ) {
948 ptr = strrchr(ptr, '/');
949 prelude_string_set_dup(str, ptr + 1);
950 }
951 } else {
952 ret = idmef_process_new_name(process, &str);
953 if ( ret == 0 ) {
954 prelude_string_set_dup(str, ptr);
955 }
956 }
957
958 idmef_process_set_pid(process, strtoul(tmp, NULL, 0));
959 }
960
961 if (tmp)
962 free(tmp);
963
964 return 0;
965}
966#endif
967
968static int get_login_info(char *msg, idmef_alert_t *alert)
969{
970 int ret;
971 char *ptr, *ip;
972 idmef_user_t *user;
973 idmef_node_t *node;
974 struct passwd *pw;
975#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
976 struct passwd pwd;
977 char * buffer;
978#endif
979 prelude_string_t *str;
980 idmef_user_id_t *user_id;
981 idmef_address_t *address;
982 idmef_target_t *target = idmef_alert_get_next_target(alert, NULL);
983 idmef_source_t *source = idmef_alert_get_next_source(alert, NULL);
984
985 ip = ptr = get_value(msg, _("ip"), NULL);
986 if ( ptr ) {
987 if ( ! source ) {
988 ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
989 if ( ret < 0 ) {
990 free(ptr);
991 return ret;
992 }
993 }
994
995 ret = idmef_source_new_node(source, &node);
996 if ( ret < 0 ) {
997 free(ptr);
998 return ret;
999 }
1000
1001 ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND);
1002 if ( ret < 0 ) {
1003 free(ptr);
1004 return ret;
1005 }
1006
1007 ret = idmef_address_new_address(address, &str);
1008 if ( ret < 0 ) {
1009 free(ptr);
1010 return ret;
1011 }
1012
1013 prelude_string_set_nodup(str, ptr);
1014 }
1015
1016 ptr = get_value(msg, _("host"), NULL);
1017 if ( ptr ) {
1018 if ( ip && strcmp(ptr, ip) == 0 )
1019 free(ptr);
1020 else {
1021 if ( ! source ) {
1022 ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
1023 if ( ret < 0 ) {
1024 free(ptr);
1025 return ret;
1026 }
1027 }
1028
1029 ret = idmef_source_new_node(source, &node);
1030 if ( ret < 0 ) {
1031 free(ptr);
1032 return ret;
1033 }
1034
1035 ret = idmef_node_new_name(node, &str);
1036 if ( ret < 0 ) {
1037 free(ptr);
1038 return ret;
1039 }
1040
1041 prelude_string_set_nodup(str, ptr);
1042 }
1043 }
1044
1045 ptr = get_value(msg, _("name"), NULL);
1046 if ( ptr ) {
1047 ret = idmef_target_new_user(target, &user);
1048 if ( ret < 0 ) {
1049 free(ptr);
1050 return ret;
1051 }
1052
1053 idmef_user_set_category(user, IDMEF_USER_CATEGORY_OS_DEVICE);
1054
1055 ret = idmef_user_new_user_id(user, &user_id, IDMEF_LIST_APPEND);
1056 if ( ret < 0 ) {
1057 free(ptr);
1058 return ret;
1059 }
1060
1061 idmef_user_id_set_type(user_id, IDMEF_USER_ID_TYPE_TARGET_USER);
1062
1063#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1064 buffer = SH_ALLOC(SH_PWBUF_SIZE);
1065 sh_getpwnam_r(ptr, &pwd, buffer, SH_PWBUF_SIZE, &pw);
1066#else
1067 pw = sh_getpwnam(ptr);
1068#endif
1069 if ( pw )
1070 idmef_user_id_set_number(user_id, pw->pw_uid);
1071
1072 ret = idmef_user_id_new_name(user_id, &str);
1073 if ( ret < 0 ) {
1074 free(ptr);
1075#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1076 SH_FREE(buffer);
1077#endif
1078 return ret;
1079 }
1080 prelude_string_set_nodup(str, ptr);
1081
1082 ptr = get_value(msg, _("tty"), NULL);
1083 if ( ptr ) {
1084 ret = idmef_user_id_new_tty(user_id, &str);
1085 if ( ret < 0 ) {
1086 free(ptr);
1087#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1088 SH_FREE(buffer);
1089#endif
1090 return ret;
1091 }
1092
1093 prelude_string_set_nodup(str, ptr);
1094 }
1095#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1096 SH_FREE(buffer);
1097#endif
1098 }
1099
1100 ptr = get_time_value(msg, _("time"), NULL);
1101 if ( ptr ) {
1102 idmef_time_t *time;
1103
1104 ret = idmef_time_from_samhain(&time, ptr);
1105 free(ptr);
1106
1107 if ( ret < 0 )
1108 return ret;
1109
1110 idmef_alert_set_detect_time(alert, time);
1111 }
1112
1113 return 0;
1114}
1115
1116
1117static int samhain_alert_prelude(int priority, int sh_class,
1118 char *message, unsigned long msgid)
1119{
1120 int ret;
1121 idmef_time_t *time;
1122 idmef_alert_t *alert;
1123 idmef_message_t *idmef;
1124 idmef_classification_t *classification;
1125 idmef_assessment_t *assessment;
1126 idmef_additional_data_t *data;
1127 idmef_impact_t *impact;
1128 idmef_target_t *target;
1129 idmef_confidence_t *confidence;
1130 prelude_string_t *str;
1131
1132 if ( !client || sh_class == STAMP)
1133 return 0;
1134
1135 ret = idmef_message_new(&idmef);
1136 if ( ret < 0 )
1137 goto err;
1138
1139 ret = idmef_message_new_alert(idmef, &alert);
1140 if ( ret < 0 )
1141 goto err;
1142
1143 idmef_alert_set_analyzer(alert, idmef_analyzer_ref(prelude_client_get_analyzer(client)), IDMEF_LIST_PREPEND);
1144
1145 ret = idmef_time_new_from_gettimeofday(&time);
1146 if ( ret < 0 )
1147 goto err;
1148 idmef_alert_set_detect_time(alert, time);
1149
1150 ret = idmef_time_new_from_gettimeofday(&time);
1151 if ( ret < 0 )
1152 goto err;
1153 idmef_alert_set_create_time(alert, time);
1154
1155 ret = idmef_alert_new_classification(alert, &classification);
1156 if ( ret < 0 )
1157 goto err;
1158
1159 ret = idmef_alert_new_target(alert, &target, IDMEF_LIST_APPEND);
1160 if ( ret < 0 )
1161 goto err;
1162
1163 idmef_target_set_decoy(target, IDMEF_TARGET_DECOY_NO);
1164
1165 if ( idmef_analyzer_get_node(prelude_client_get_analyzer(client)) ) {
1166 idmef_node_ref(idmef_analyzer_get_node(prelude_client_get_analyzer(client)));
1167 idmef_target_set_node(target, idmef_analyzer_get_node(prelude_client_get_analyzer(client)));
1168 }
1169
1170 if ( strstr(message, _("path=")) ) {
1171#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
1172 if ( msgid != MSG_FI_ADD && msgid != MSG_FI_ADD2 )
1173 get_file_infos(target, message, IDMEF_FILE_CATEGORY_ORIGINAL);
1174#endif
1175
1176 get_file_infos(target, message, IDMEF_FILE_CATEGORY_CURRENT);
1177 }
1178
1179 ret = idmef_alert_new_assessment(alert, &assessment);
1180 if ( ret < 0 )
1181 goto err;
1182
1183 ret = idmef_assessment_new_impact(assessment, &impact);
1184 if ( ret < 0 )
1185 goto err;
1186
1187 ret = idmef_classification_new_text(classification, &str);
1188 if ( ret < 0 )
1189 goto err;
1190
1191 ret = get_login_info(message, alert);
1192 if ( ret < 0 )
1193 goto err;
1194
1195#ifdef SH_USE_PORTCHECK
1196 if (msgid == MSG_PORT_MISS || msgid == MSG_PORT_NEW || msgid == MSG_PORT_RESTART || msgid == MSG_PORT_NEWPORT) {
1197 ret = get_service_info(message, alert);
1198 if ( ret < 0 )
1199 goto err;
1200 }
1201#endif
1202
1203 map_policy_to_class(message, msgid, impact, str);
1204
1205#if 0
1206 if ( priority == SH_ERR_SEVERE || priority == SH_ERR_FATAL )
1207 idmef_impact_set_severity(impact, IDMEF_IMPACT_SEVERITY_HIGH);
1208
1209 else if ( priority == SH_ERR_ALL || priority == SH_ERR_INFO || priority == SH_ERR_NOTICE )
1210 idmef_impact_set_severity(impact, IDMEF_IMPACT_SEVERITY_LOW);
1211
1212 else
1213 idmef_impact_set_severity(impact, IDMEF_IMPACT_SEVERITY_MEDIUM);
1214#endif
1215 idmef_impact_set_severity(impact, map_severity(priority));
1216
1217 idmef_impact_set_completion(impact, IDMEF_IMPACT_COMPLETION_SUCCEEDED);
1218
1219 ret = idmef_assessment_new_confidence(assessment, &confidence);
1220 if ( ret < 0 )
1221 goto err;
1222
1223 idmef_confidence_set_rating(confidence, IDMEF_CONFIDENCE_RATING_HIGH);
1224
1225 ret = idmef_alert_new_additional_data(alert, &data, IDMEF_LIST_APPEND);
1226 if ( ret < 0 )
1227 goto err;
1228
1229 ret = idmef_additional_data_new_meaning(data, &str);
1230 if ( ret < 0 )
1231 goto err;
1232
1233 prelude_string_set_dup(str, _("Message generated by Samhain"));
1234 idmef_additional_data_set_type(data, IDMEF_ADDITIONAL_DATA_TYPE_STRING);
1235 idmef_additional_data_set_string_ref(data, message);
1236
1237 /* debug_print_message(idmef); */
1238
1239 prelude_client_send_idmef(client, idmef);
1240 idmef_message_destroy(idmef);
1241
1242 return 0;
1243
1244 err:
1245 idmef_message_destroy(idmef);
1246 return -1;
1247}
1248
1249
1250int sh_prelude_alert(int priority, int sh_class, char *message, long msgflags, unsigned long msgid)
1251{
1252 int ret;
1253
1254 (void) msgflags; /* fix compiler warning */
1255
1256 if ( initialized < 1 )
1257 return -1;
1258
1259 ret = samhain_alert_prelude(priority, sh_class, message, msgid);
1260 if ( ret < 0 ) {
1261 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1262 _("Problem with IDMEF for prelude-ids support: alert lost"),
1263 _("sh_prelude_alert"));
1264 }
1265
1266 return ret;
1267}
1268
1269
1270
1271int sh_prelude_set_profile(const char *arg)
1272{
1273 if ( profile ) {
1274 free(profile);
1275 profile = NULL;
1276 }
1277
1278 if ( arg ) {
1279 profile = strdup(arg);
1280 if ( ! profile )
1281 return -1;
1282 }
1283
1284 return 0;
1285}
1286
1287/* Allow initialization of prelude; to be called
1288 * after forking the daemon. Delays heartbeat
1289 * start after config read until it is safe.
1290 */
1291void sh_prelude_reset(void)
1292{
1293 extern void sh_error_init_prelude();
1294
1295 ready_for_init = 1;
1296 sh_error_init_prelude();
1297 return;
1298}
1299
1300
1301
1302void sh_prelude_stop(void)
1303{
1304 if (initialized < 1)
1305 return;
1306
1307 if (sh.flag.isdaemon == S_TRUE)
1308 prelude_client_destroy(client, PRELUDE_CLIENT_EXIT_STATUS_FAILURE);
1309 else
1310 prelude_client_destroy(client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS);
1311
1312 client = NULL;
1313
1314 prelude_deinit();
1315
1316 initialized = 0;
1317 return;
1318}
1319
1320
1321
1322int sh_prelude_init(void)
1323{
1324 int ret;
1325 prelude_string_t *str;
1326 idmef_analyzer_t *analyzer;
1327 prelude_client_flags_t flags;
1328#ifdef SH_NOFAILOVER
1329 prelude_connection_pool_t *pool;
1330 prelude_connection_pool_flags_t conn_flags;
1331#endif
1332
1333 if (ready_for_init == 0)
1334 return initialized;
1335
1336 if (initialized > 0)
1337 return initialized;
1338
1339 prelude_thread_init(NULL);
1340 prelude_init(&sh_argc_store, sh_argv_store);
1341
1342 ret = prelude_client_new(&client, profile ? profile : _("samhain"));
1343 if ( ret < 0 ) {
1344 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1345 _("Failed to initialize Prelude"), _("sh_prelude_init"));
1346 initialized = -1;
1347 return -1;
1348 }
1349
1350 /*
1351 * Enable automatic heartbeat sending.
1352 */
1353 flags = prelude_client_get_flags(client);
1354 ret = prelude_client_set_flags(client, flags | PRELUDE_CLIENT_FLAGS_ASYNC_TIMER);
1355
1356 analyzer = prelude_client_get_analyzer(client);
1357
1358 ret = idmef_analyzer_new_model(analyzer, &str);
1359 prelude_string_set_dup(str, IDMEF_ANALYZER_MODEL);
1360
1361 ret = idmef_analyzer_new_class(analyzer, &str);
1362 prelude_string_set_dup(str, IDMEF_ANALYZER_CLASS);
1363
1364 ret = idmef_analyzer_new_version(analyzer, &str);
1365 prelude_string_set_dup(str, IDMEF_ANALYZER_VERSION);
1366
1367#ifdef SH_NOFAILOVER
1368 pool = prelude_client_get_connection_pool(client);
1369 conn_flags = prelude_connection_pool_get_flags(pool);
1370
1371 conn_flags &= ~PRELUDE_CONNECTION_POOL_FLAGS_FAILOVER;
1372 prelude_connection_pool_set_flags(pool, conn_flags);
1373#endif
1374
1375 ret = prelude_client_start(client);
1376 if ( ret < 0 ) {
1377 prelude_perror(ret, _("error starting prelude client"));
1378
1379 if ( prelude_client_is_setup_needed(ret) )
1380 prelude_client_print_setup_error(client);
1381
1382 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1383 _("Failed to start Prelude"), _("sh_prelude_init"));
1384 initialized = -1;
1385 return -1;
1386 }
1387
1388 initialized = 1;
1389 return 1;
1390}
1391
1392/* HAVE_LIBPRELUDE_9 */
1393#endif
1394
Note: See TracBrowser for help on using the repository browser.