~wibblymat/ubuntu/oneiric/sagan/ftbfs-jam

« back to all changes in this revision

Viewing changes to src/output-plugins/sagan-prelude.c

  • Committer: Bazaar Package Importer
  • Author(s): Pierre Chifflier
  • Date: 2011-03-17 15:18:58 UTC
  • Revision ID: james.westby@ubuntu.com-20110317151858-iqvfx0hsxlamxp6b
Tags: upstream-0.1.9~svn129
ImportĀ upstreamĀ versionĀ 0.1.9~svn129

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** Copyright (C) 2009-2011 Softwink, Inc. 
 
3
** Copyright (C) 2009-2011 Champ Clark III <champ@softwink.com>
 
4
**
 
5
** This program is free software; you can redistribute it and/or modify
 
6
** it under the terms of the GNU General Public License Version 2 as
 
7
** published by the Free Software Foundation.  You may not use, modify or
 
8
** distribute this program under any other version of the GNU General
 
9
** Public License.
 
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
19
*/
 
20
 
 
21
/* sagan-prelude.c 
 
22
 *
 
23
 * Threaded output for the Prelude framework.  For more information about
 
24
 * Prelude,  please see: http://www.prelude-technologies.com
 
25
 * 
 
26
 * Some of this code is based off Snort's Prelude output plug in 
 
27
 * (spo_alert_prelude.c). 
 
28
 *
 
29
 */
 
30
 
 
31
 
 
32
#ifdef HAVE_CONFIG_H
 
33
#include "config.h"             /* From autoconf */
 
34
#endif
 
35
 
 
36
#ifdef HAVE_LIBPRELUDE
 
37
 
 
38
#include <stdio.h>
 
39
#include <string.h>
 
40
#include <libprelude/prelude.h>
 
41
#include <pthread.h>
 
42
#include <inttypes.h>
 
43
#include "version.h"
 
44
 
 
45
#include "sagan.h"
 
46
#include "sagan-prelude.h"
 
47
 
 
48
struct _SaganConfig *config;
 
49
struct _SaganCounters *counters;
 
50
 
 
51
#define ANALYZER_CLASS "Log Analyzer"
 
52
#define ANALYZER_MODEL "Sagan"
 
53
#define ANALYZER_MANUFACTURER "http://sagan.softwink.com"
 
54
#define ANALYZER_SID_URL "https://wiki.softwink.com/bin/view/Main/"
 
55
#define DEFAULT_ANALYZER_NAME "sagan"
 
56
#define ANALYZER_INTERFACE "syslog"
 
57
 
 
58
prelude_client_t *preludeclient;
 
59
 
 
60
struct rule_struct *rulestruct;
 
61
 
 
62
/* Init the Prelude sub system. */
 
63
 
 
64
void PreludeInit(void) 
 
65
{
 
66
 
 
67
int ret; 
 
68
 
 
69
prelude_client_flags_t flags;
 
70
 
 
71
ret = prelude_thread_init(NULL);
 
72
 
 
73
if ( ret < 0 ) { 
 
74
        removelockfile(); 
 
75
        sagan_log(1, "[%s, line %d] %s: Unable to init the Prelude thread subsystem: %s", __FILE__, __LINE__, prelude_strsource(ret), prelude_strerror(ret));
 
76
        }
 
77
 
 
78
ret = prelude_init(NULL, NULL);
 
79
if ( ret < 0 ) {
 
80
        removelockfile();
 
81
        sagan_log(1, "[%s, line %d] %s: Unable to init the Prelude library: %s", __FILE__, __LINE__, prelude_strsource(ret), prelude_strerror(ret));
 
82
        }
 
83
 
 
84
ret = prelude_client_new(&preludeclient, config->sagan_prelude_profile ? config->sagan_prelude_profile : DEFAULT_ANALYZER_NAME);
 
85
 
 
86
if ( ret < 0 ) {
 
87
        removelockfile();
 
88
        sagan_log(1, "[%s, line %d] %s: Unable to create a Prelude client object: %s", __FILE__, __LINE__, prelude_strsource(ret), prelude_strerror(ret));
 
89
        }
 
90
 
 
91
flags = PRELUDE_CLIENT_FLAGS_ASYNC_SEND|PRELUDE_CLIENT_FLAGS_ASYNC_TIMER;
 
92
ret = prelude_client_set_flags(preludeclient, prelude_client_get_flags(preludeclient) | flags);
 
93
 
 
94
if ( ret < 0 ) {
 
95
        removelockfile();
 
96
        sagan_log(1, "[%s, line %d] %s: Unable to set asynchronous send and timer: %s", __FILE__, __LINE__, prelude_strsource(ret), prelude_strerror(ret));
 
97
        }
 
98
 
 
99
setup_analyzer(prelude_client_get_analyzer(preludeclient));
 
100
 
 
101
ret = prelude_client_start(preludeclient);
 
102
if ( ret < 0 ) {
 
103
        removelockfile();
 
104
        sagan_log(1, "[%s, line %d] %s: Unable to initialize Prelude client: %s", __FILE__, __LINE__, prelude_strsource(ret), prelude_strerror(ret));
 
105
        }
 
106
 
 
107
 
 
108
}
 
109
 
 
110
/* Setup's up the Prelude analyzer.  This is information like model, 
 
111
 * class, etc */
 
112
 
 
113
int setup_analyzer(idmef_analyzer_t *analyzer)
 
114
{
 
115
        int ret;
 
116
        prelude_string_t *string;
 
117
 
 
118
        ret = idmef_analyzer_new_model(analyzer, &string);
 
119
        if ( ret < 0 )
 
120
                return ret;
 
121
        prelude_string_set_constant(string, ANALYZER_MODEL);
 
122
 
 
123
        ret = idmef_analyzer_new_class(analyzer, &string);
 
124
        if ( ret < 0 )
 
125
                return ret;
 
126
        prelude_string_set_constant(string, ANALYZER_CLASS);
 
127
 
 
128
        ret = idmef_analyzer_new_manufacturer(analyzer, &string);
 
129
        if ( ret < 0 )
 
130
                return ret;
 
131
        prelude_string_set_constant(string, ANALYZER_MANUFACTURER);
 
132
 
 
133
        ret = idmef_analyzer_new_version(analyzer, &string);
 
134
        if ( ret < 0 )
 
135
                return ret;
 
136
        prelude_string_set_constant(string, VERSION);
 
137
 
 
138
 
 
139
        return 0;
 
140
}
 
141
 
 
142
int add_int_data(idmef_alert_t *alert, const char *meaning, uint32_t data)
 
143
{
 
144
        int ret;
 
145
        prelude_string_t *str;
 
146
        idmef_additional_data_t *ad;
 
147
 
 
148
        ret = idmef_alert_new_additional_data(alert, &ad, IDMEF_LIST_APPEND);
 
149
        if ( ret < 0 )
 
150
                return ret;
 
151
 
 
152
        idmef_additional_data_set_integer(ad, data);
 
153
 
 
154
        ret = idmef_additional_data_new_meaning(ad, &str);
 
155
        if ( ret < 0 ) {
 
156
                sagan_log(0,"%s: error creating additional-data meaning: %s.\n",
 
157
                             prelude_strsource(ret), prelude_strerror(ret));
 
158
                return -1;
 
159
        }
 
160
 
 
161
        ret = prelude_string_set_ref(str, meaning);
 
162
        if ( ret < 0 ) {
 
163
                sagan_log(0, "%s: error setting integer data meaning: %s.\n",
 
164
                             prelude_strsource(ret), prelude_strerror(ret));
 
165
                return -1;
 
166
        }
 
167
 
 
168
        return 0;
 
169
}
 
170
 
 
171
 
 
172
/****************************************************************************/
 
173
/* sagan_prelude() - This is the sub/thread called from the main process    */
 
174
/****************************************************************************/
 
175
 
 
176
void sagan_prelude( SaganEvent *Event ) 
 
177
{
 
178
 
 
179
pthread_mutex_t prelude_mutex = PTHREAD_MUTEX_INITIALIZER;
 
180
 
 
181
int ret;
 
182
 
 
183
int sid=0;
 
184
int rev=0;
 
185
 
 
186
idmef_message_t *idmef;
 
187
idmef_alert_t *alert;
 
188
idmef_classification_t *class;
 
189
prelude_string_t *str;
 
190
 
 
191
/* IDMEF message init */
 
192
 
 
193
ret = idmef_message_new(&idmef);
 
194
if ( ret < 0 ) {
 
195
         prelude_client_destroy(preludeclient, PRELUDE_CLIENT_EXIT_STATUS_FAILURE);
 
196
         sagan_log(1, "[%s, line %d] Error in idmef_message_new(). Aborting", __FILE__, __LINE__);
 
197
         }
 
198
 
 
199
ret = idmef_message_new_alert(idmef, &alert);
 
200
      if ( ret < 0 ) { 
 
201
         sagan_log(0, "[%s, line %d] Error in idmef_message_new_alert()", __FILE__, __LINE__); 
 
202
         goto err;
 
203
         }
 
204
 
 
205
ret = idmef_alert_new_classification(alert, &class);
 
206
      if ( ret < 0 ) {
 
207
         sagan_log(0, "[%s, line %d] Error in idmef_alert_new_classification()", __FILE__, __LINE__);
 
208
         goto err;
 
209
         }
 
210
ret = idmef_classification_new_text(class, &str);
 
211
      if ( ret < 0 ) {
 
212
         sagan_log(0, "[%s, line %d] Error in idmef_classification_new_text()", __FILE__, __LINE__);
 
213
         goto err;
 
214
         }
 
215
 
 
216
prelude_string_set_ref(str, rulestruct[Event->found].s_msg );
 
217
 
 
218
ret = event_to_impact(rulestruct[Event->found].s_pri, alert);
 
219
      if ( ret < 0 ) {
 
220
         sagan_log(0, "[%s, line %d] event_to_impact() failed", __FILE__, __LINE__);
 
221
         goto err;
 
222
         }
 
223
 
 
224
ret = event_to_reference(rulestruct[Event->found].s_sid, class);
 
225
      if ( ret < 0 ) {
 
226
         sagan_log(0, "[%s, line %d] event_to_reference() failed", __FILE__, __LINE__);
 
227
         goto err;
 
228
         }
 
229
 
 
230
ret = event_to_source_target(Event->ip_src, Event->ip_dst, Event->src_port, Event->dst_port, rulestruct[Event->found].ip_proto, alert);
 
231
      if ( ret < 0 ) {
 
232
         sagan_log(0, "[%s, line %d] event_to_source_target() failed", __FILE__, __LINE__);
 
233
         goto err;
 
234
         }
 
235
 
 
236
sid = atoi(rulestruct[Event->found].s_sid);
 
237
rev = atoi(rulestruct[Event->found].s_rev);
 
238
 
 
239
ret = syslog_to_data(rulestruct[Event->found].s_sid, rulestruct[Event->found].s_rev, rulestruct[Event->found].ip_proto, Event->message, alert);
 
240
      if ( ret < 0 ) {
 
241
         sagan_log(0, "[%s, line %d] syslog_to_data() failed", __FILE__, __LINE__);
 
242
         goto err;
 
243
         }
 
244
 
 
245
prelude_client_send_idmef(preludeclient, idmef);
 
246
 
 
247
err:
 
248
idmef_message_destroy(idmef);
 
249
 
 
250
pthread_mutex_lock ( &prelude_mutex );
 
251
counters->threadpreludec--;
 
252
pthread_mutex_unlock ( &prelude_mutex );
 
253
 
 
254
pthread_exit(NULL);
 
255
}
 
256
 
 
257
/* Assigns severity to an event.  For example,  priority 1 == High */
 
258
 
 
259
int event_to_impact(int pri, idmef_alert_t *alert) 
 
260
{
 
261
 
 
262
int ret;
 
263
idmef_impact_t *impact;
 
264
idmef_impact_severity_t severity;
 
265
idmef_assessment_t *assessment;
 
266
 
 
267
ret = idmef_alert_new_assessment(alert, &assessment);
 
268
      if ( ret < 0 ) sagan_log(1, "[%s, line %d] Error in idmef_alert_new_assessment(). Abort.", __FILE__, __LINE__);
 
269
 
 
270
ret = idmef_assessment_new_impact(assessment,  &impact);
 
271
      if ( ret < 0 ) sagan_log(1,"[%s, line %d] Error in idmef_assessment_new_impact(). Abort.", __FILE__, __LINE__);
 
272
 
 
273
if ( pri == 1 ) severity = IDMEF_IMPACT_SEVERITY_HIGH;
 
274
else if ( pri == 2 ) severity = IDMEF_IMPACT_SEVERITY_MEDIUM;
 
275
else if ( pri == 3 ) severity = IDMEF_IMPACT_SEVERITY_LOW;
 
276
else  severity = IDMEF_IMPACT_SEVERITY_INFO;
 
277
 
 
278
idmef_impact_set_severity(impact, severity);
 
279
return 0;
 
280
 
 
281
}
 
282
 
 
283
 
 
284
int event_to_reference(char *sid , idmef_classification_t *class)
 
285
{
 
286
int ret;
 
287
prelude_string_t *str;
 
288
 
 
289
ret = idmef_classification_new_ident(class, &str);
 
290
      if ( ret < 0 ) return ret; 
 
291
 
 
292
ret = prelude_string_sprintf(str, "%s", sid);
 
293
if ( ret < 0 ) return ret; 
 
294
 
 
295
ret = add_sagan_reference(class, sid); 
 
296
 
 
297
return ret;
 
298
}
 
299
 
 
300
/* Supply target/source/port information */
 
301
 
 
302
int event_to_source_target(char *ip_src, char *ip_dst, int src_port, int dst_port, int proto, idmef_alert_t *alert)
 
303
{
 
304
 
 
305
int ret;
 
306
idmef_source_t *source;
 
307
idmef_service_t *service;
 
308
prelude_string_t *string;
 
309
idmef_node_t *node;
 
310
idmef_address_t *address;
 
311
idmef_target_t *target;
 
312
 
 
313
 
 
314
ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
 
315
if ( ret < 0 ) return ret;
 
316
 
 
317
ret = idmef_source_new_interface(source, &string);
 
318
if ( ret < 0 ) return ret;
 
319
 
 
320
prelude_string_set_ref(string, config->sagan_interface);
 
321
 
 
322
ret = idmef_source_new_service(source, &service);
 
323
if ( ret < 0 ) return ret;
 
324
 
 
325
idmef_service_set_port(service, src_port );
 
326
if ( ret < 0 ) return ret;
 
327
 
 
328
idmef_service_set_ip_version(service, 4);
 
329
idmef_service_set_iana_protocol_number(service, proto);
 
330
 
 
331
ret = idmef_source_new_node(source, &node);
 
332
if ( ret < 0 ) return ret;
 
333
 
 
334
ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND);
 
335
if ( ret < 0 ) return ret;
 
336
 
 
337
ret = idmef_address_new_address(address, &string);
 
338
if ( ret < 0 ) return ret;
 
339
 
 
340
prelude_string_set_ref(string, ip_src);
 
341
 
 
342
ret = idmef_alert_new_target(alert, &target, IDMEF_LIST_APPEND);
 
343
if ( ret < 0 ) return ret;
 
344
 
 
345
ret = idmef_target_new_interface(target, &string);
 
346
if ( ret < 0 ) return ret;
 
347
 
 
348
ret = idmef_target_new_service(target, &service);
 
349
if ( ret < 0 ) return ret;
 
350
 
 
351
/* Target */
 
352
idmef_service_set_port(service, dst_port);
 
353
if ( ret < 0 ) return ret;
 
354
 
 
355
idmef_service_set_ip_version(service, 4);
 
356
idmef_service_set_iana_protocol_number(service, proto );
 
357
 
 
358
ret = idmef_target_new_node(target, &node);
 
359
if ( ret < 0 ) return ret;
 
360
 
 
361
ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND);
 
362
if ( ret < 0 ) return ret;
 
363
 
 
364
ret = idmef_address_new_address(address, &string);
 
365
if ( ret < 0 ) return ret;
 
366
 
 
367
prelude_string_set_ref(string, ip_dst);
 
368
 
 
369
return 0;
 
370
}
 
371
 
 
372
int syslog_to_data ( char *sid,  char *rev, int proto, char *message, idmef_alert_t *alert )
 
373
{
 
374
 
 
375
int i;
 
376
 
 
377
i = atoi(sid);
 
378
add_int_data(alert, "sagan_rule_sid", i);
 
379
i = atoi(rev);
 
380
add_int_data(alert, "sagan_rule_rev", i );
 
381
 
 
382
add_int_data(alert, "ip_ver", 4);
 
383
 
 
384
add_int_data(alert, "ip_proto", proto);
 
385
 
 
386
 
 
387
add_byte_data(alert, "payload", message, strlen(message));
 
388
 
 
389
 
 
390
return 0;
 
391
}
 
392
 
 
393
/* Setup for the payload information */
 
394
 
 
395
int add_byte_data(idmef_alert_t *alert, const char *meaning, const unsigned char *data, size_t size)
 
396
{
 
397
 
 
398
int ret;
 
399
prelude_string_t *str;
 
400
idmef_additional_data_t *ad;
 
401
 
 
402
ret = idmef_alert_new_additional_data(alert, &ad, IDMEF_LIST_APPEND);
 
403
if ( ret < 0 ) return ret;
 
404
 
 
405
ret = idmef_additional_data_set_byte_string_ref(ad, data, size);
 
406
if ( ret < 0 )  { 
 
407
        sagan_log(0, "[%s, line %d] %s Error setting byte string data: %s", __FILE__, __LINE__, prelude_strsource(ret), prelude_strerror(ret));
 
408
        return -1;
 
409
        }
 
410
 
 
411
ret = idmef_additional_data_new_meaning(ad, &str);
 
412
if ( ret < 0 )  {
 
413
        sagan_log(0, "[%s, line %d] %s Error creating additional-data meaning: %s", __FILE__, __LINE__, prelude_strsource(ret), prelude_strerror(ret));
 
414
        return -1;
 
415
        }
 
416
 
 
417
ret = prelude_string_set_ref(str, meaning);
 
418
if ( ret < 0 )  {
 
419
        sagan_log(0, "[%s, line %d] %s Error setting byte string data meaning: %s", __FILE__, __LINE__, prelude_strsource(ret), prelude_strerror(ret));
 
420
        return -1;
 
421
        }
 
422
 
 
423
return 0;
 
424
}
 
425
 
 
426
int add_sagan_reference(idmef_classification_t *class, char *sid)
 
427
{
 
428
 
 
429
int ret; 
 
430
int i;
 
431
prelude_string_t *str;
 
432
idmef_reference_t *ref;
 
433
 
 
434
i = atol(sid);
 
435
 
 
436
if ( i != 0 ) { 
 
437
 
 
438
ret = idmef_classification_new_reference(class, &ref, IDMEF_LIST_APPEND);
 
439
if ( ret < 0 ) return ret;   
 
440
 
 
441
ret = idmef_reference_new_name(ref, &str);
 
442
if ( ret < 0 ) return ret;
 
443
 
 
444
idmef_reference_set_origin(ref, IDMEF_REFERENCE_ORIGIN_VENDOR_SPECIFIC);
 
445
ret = prelude_string_sprintf(str, "%s", sid);
 
446
if ( ret < 0 ) return ret;
 
447
 
 
448
ret = idmef_reference_new_meaning(ref, &str);
 
449
if ( ret < 0 ) return ret;
 
450
 
 
451
ret = prelude_string_sprintf(str, "Sagan Signature ID");
 
452
if ( ret < 0 ) return ret;
 
453
 
 
454
ret = idmef_reference_new_url(ref, &str);
 
455
if ( ret < 0 ) return ret;
 
456
 
 
457
ret = prelude_string_sprintf(str, ANALYZER_SID_URL "%s", sid);
 
458
return ret;
 
459
   }
 
460
 
 
461
return(0);
 
462
 
 
463
}
 
464
 
 
465
#endif