1 /*
2 * Copyright (c) 2010-2015 Balabit
3 * Copyright (c) 2015 Viktor Juhasz <viktor.juhasz@balabit.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * As an additional exemption you are allowed to compile & link against the
20 * OpenSSL libraries as published by the OpenSSL project. See the file
21 * COPYING for details.
22 *
23 */
24
25 #include "logmsg/logmsg-serialize.h"
26 #include "logmsg/logmsg-serialize-fixup.h"
27 #include "logmsg/nvtable-serialize.h"
28 #include "logmsg/nvtable-serialize-legacy.h"
29 #include "logmsg/gsockaddr-serialize.h"
30 #include "logmsg/timestamp-serialize.h"
31 #include "logmsg/tags-serialize.h"
32 #include "messages.h"
33
34 #include <stdlib.h>
35
36
37 #define OLD_LMM_REF_MATCH 0x0001
38
39 static void
_setup_ts_processed(UnixTime * timestamps,const UnixTime * processed)40 _setup_ts_processed(UnixTime *timestamps, const UnixTime *processed)
41 {
42 if (processed != NULL)
43 timestamps[LM_TS_PROCESSED] = *processed;
44 else if (!unix_time_is_set(×tamps[LM_TS_PROCESSED]))
45 timestamps[LM_TS_PROCESSED] = timestamps[LM_TS_RECVD];
46 }
47
48 static void
nv_table_serialize_with_compaction(LogMessageSerializationState * state,NVTable * old)49 nv_table_serialize_with_compaction(LogMessageSerializationState *state, NVTable *old)
50 {
51 NVTable *payload;
52 payload = nv_table_compact(old);
53 nv_table_serialize(state, payload);
54 nv_table_unref(payload);
55 };
56
57 static gboolean
_serialize_message(LogMessageSerializationState * state)58 _serialize_message(LogMessageSerializationState *state)
59 {
60 LogMessage *msg = state->msg;
61 SerializeArchive *sa = state->sa;
62 UnixTime timestamps[LM_TS_MAX];
63
64 memcpy(×tamps, msg->timestamps, LM_TS_MAX*sizeof(UnixTime));
65 _setup_ts_processed(timestamps, state->processed);
66
67 serialize_write_uint8(sa, state->version);
68 serialize_write_uint64(sa, msg->rcptid);
69 g_assert(sizeof(msg->flags) == 4);
70 serialize_write_uint32(sa, msg->flags & ~LF_STATE_MASK);
71 serialize_write_uint16(sa, msg->pri);
72 g_sockaddr_serialize(sa, msg->saddr);
73 timestamp_serialize(sa, timestamps);
74 serialize_write_uint32(sa, msg->host_id);
75 tags_serialize(msg, sa);
76 serialize_write_uint8(sa, msg->initial_parse);
77 serialize_write_uint8(sa, msg->num_matches);
78 serialize_write_uint8(sa, msg->num_sdata);
79 serialize_write_uint8(sa, msg->alloc_sdata);
80 serialize_write_uint32_array(sa, (guint32 *) msg->sdata, msg->num_sdata);
81
82 if (state->flags & LMSF_COMPACTION)
83 nv_table_serialize_with_compaction(state, msg->payload);
84 else
85 nv_table_serialize(state, msg->payload);
86 return TRUE;
87 }
88
89 gboolean
log_msg_serialize_with_ts_processed(LogMessage * self,SerializeArchive * sa,const UnixTime * processed,guint32 flags)90 log_msg_serialize_with_ts_processed(LogMessage *self, SerializeArchive *sa, const UnixTime *processed, guint32 flags)
91 {
92 LogMessageSerializationState state = { 0 };
93
94 state.version = LGM_V26;
95 state.msg = self;
96 state.sa = sa;
97 state.processed = processed;
98 state.flags = flags;
99 return _serialize_message(&state);
100 }
101
102 gboolean
log_msg_serialize(LogMessage * self,SerializeArchive * sa,guint32 flags)103 log_msg_serialize(LogMessage *self, SerializeArchive *sa, guint32 flags)
104 {
105 return log_msg_serialize_with_ts_processed(self, sa, NULL, flags);
106 }
107
108 static gboolean
_deserialize_sdata(LogMessageSerializationState * state)109 _deserialize_sdata(LogMessageSerializationState *state)
110 {
111 LogMessage *self = state->msg;
112 SerializeArchive *sa = state->sa;
113
114 if (!serialize_read_uint8(sa, &self->num_sdata))
115 return FALSE;
116
117 if (!serialize_read_uint8(sa, &self->alloc_sdata))
118 return FALSE;
119
120 g_assert(!self->sdata);
121 self->sdata = (NVHandle *) g_malloc(sizeof(NVHandle)*self->alloc_sdata);
122
123 if (state->version <= LGM_V20)
124 return TRUE;
125
126 if ((state->version < LGM_V26) && !serialize_read_uint16_array(sa, (guint32 *) self->sdata, self->num_sdata))
127 return FALSE;
128
129 if ((state->version == LGM_V26) && !serialize_read_uint32_array(sa, (guint32 *) self->sdata, self->num_sdata))
130 return FALSE;
131
132 return TRUE;
133 }
134
135 NVTable *
_nv_table_deserialize_selector(LogMessageSerializationState * state)136 _nv_table_deserialize_selector(LogMessageSerializationState *state)
137 {
138 if (state->version < LGM_V22)
139 {
140 state->nvtable = nv_table_deserialize_legacy(state->sa);
141
142 return state->nvtable;
143 }
144 else if (state->version < LGM_V26)
145 {
146 state->nvtable = nv_table_deserialize_22(state->sa);
147
148 return state->nvtable;
149 }
150 else if (state->version == LGM_V26)
151 {
152 return nv_table_deserialize(state);
153 }
154
155 return NULL;
156 }
157
158 static gboolean
_deserialize_message_version_2x(LogMessageSerializationState * state)159 _deserialize_message_version_2x(LogMessageSerializationState *state)
160 {
161 g_assert(state->version >= LGM_V20);
162
163 guint8 initial_parse = 0;
164 LogMessage *msg = state->msg;
165 SerializeArchive *sa = state->sa;
166
167 if ((state->version > LGM_V22) && !serialize_read_uint64(sa, &msg->rcptid))
168 return FALSE;
169 if (!serialize_read_uint32(sa, &msg->flags))
170 return FALSE;
171 msg->flags |= LF_STATE_MASK;
172 if (!serialize_read_uint16(sa, &msg->pri))
173 return FALSE;
174 if (!g_sockaddr_deserialize(sa, &msg->saddr))
175 return FALSE;
176 if (state->version < LGM_V24)
177 {
178 if (!timestamp_deserialize_legacy(sa, msg->timestamps))
179 return FALSE;
180 msg->timestamps[LM_TS_PROCESSED] = msg->timestamps[LM_TS_RECVD];
181 }
182 if ((state->version >= LGM_V24) && !timestamp_deserialize(sa, msg->timestamps))
183 return FALSE;
184 if ((state->version >= LGM_V25) && (!serialize_read_uint32(sa, &msg->host_id)))
185 return FALSE;
186
187 if (!tags_deserialize(msg, sa))
188 return FALSE;
189
190 if (!serialize_read_uint8(sa, &initial_parse))
191 return FALSE;
192 msg->initial_parse=initial_parse;
193
194 if (!serialize_read_uint8(sa, &msg->num_matches))
195 return FALSE;
196
197 if (!_deserialize_sdata(state))
198 return FALSE;
199
200 nv_table_unref(msg->payload);
201 msg->payload = _nv_table_deserialize_selector(state);
202 if (!msg->payload)
203 return FALSE;
204
205 if (!log_msg_fixup_handles_after_deserialization(state))
206 return FALSE;
207 return TRUE;
208 }
209
210 static gboolean
log_msg_read_tags(LogMessage * self,SerializeArchive * sa)211 log_msg_read_tags(LogMessage *self, SerializeArchive *sa)
212 {
213 gchar *buf;
214 gsize len;
215
216 while (TRUE)
217 {
218 if (!serialize_read_cstring(sa, &buf, &len) || !buf)
219 return FALSE;
220 if (!buf[0])
221 {
222 /* "" , empty string means: last tag */
223 g_free(buf);
224 break;
225 }
226 log_msg_set_tag_by_name(self, buf);
227 g_free(buf);
228 }
229
230 self->flags |= LF_STATE_OWN_TAGS;
231
232 return TRUE;
233 }
234
235 /*
236 Read the most common values (HOST, HOST_FROM, PROGRAM, MESSAGE)
237 same for all version < 20
238 */
239 gboolean
log_msg_read_common_values(LogMessage * self,SerializeArchive * sa)240 log_msg_read_common_values(LogMessage *self, SerializeArchive *sa)
241 {
242 gchar *host = NULL;
243 gchar *host_from = NULL;
244 gchar *program = NULL;
245 gchar *message = NULL;
246 gsize stored_len=0;
247 if (!serialize_read_cstring(sa, &host, &stored_len))
248 return FALSE;
249 log_msg_set_value(self, LM_V_HOST, host, stored_len);
250 g_free(host);
251
252 if (!serialize_read_cstring(sa, &host_from, &stored_len))
253 return FALSE;
254 log_msg_set_value(self, LM_V_HOST_FROM, host_from, stored_len);
255 g_free(host_from);
256
257 if (!serialize_read_cstring(sa, &program, &stored_len))
258 return FALSE;
259 log_msg_set_value(self, LM_V_PROGRAM, program, stored_len);
260 g_free(program);
261
262 if (!serialize_read_cstring(sa, &message, &stored_len))
263 return FALSE;
264 log_msg_set_value(self, LM_V_MESSAGE, message, stored_len);
265 g_free(message);
266 return TRUE;
267 }
268
269 /*
270 After the matches are read the details of those have to been read
271 this process is same for version < 20
272 */
273 gboolean
log_msg_read_matches_details(LogMessage * self,SerializeArchive * sa)274 log_msg_read_matches_details(LogMessage *self, SerializeArchive *sa)
275 {
276 gint i;
277 for (i = 0; i < self->num_matches; i++)
278 {
279 guint8 stored_flags;
280 if (!serialize_read_uint8(sa, &stored_flags))
281 return FALSE;
282
283 if (stored_flags & OLD_LMM_REF_MATCH)
284 {
285 guint8 type;
286 guint16 ofs;
287 guint16 len;
288 guint8 builtin_value;
289 guint8 LM_F_MAX = 8;
290 if (!serialize_read_uint8(sa, &type) ||
291 !serialize_read_uint8(sa, &builtin_value) ||
292 builtin_value >= LM_F_MAX ||
293 !serialize_read_uint16(sa, &ofs) ||
294 !serialize_read_uint16(sa, &len))
295 return FALSE;
296 log_msg_set_match_indirect(self, i, builtin_value, type, ofs, len);
297 }
298 else
299 {
300 gchar *match = NULL;
301 gsize match_size;
302 if (!serialize_read_cstring(sa, &match, &match_size))
303 return FALSE;
304 log_msg_set_match(self, i, match, match_size);
305 g_free(match);
306 }
307 }
308 return TRUE;
309 }
310
311 static gboolean
log_msg_read_values(LogMessage * self,SerializeArchive * sa)312 log_msg_read_values(LogMessage *self, SerializeArchive *sa)
313 {
314 gchar *name = NULL, *value = NULL;
315 gboolean success = FALSE;
316
317 if (!serialize_read_cstring(sa, &name, NULL) ||
318 !serialize_read_cstring(sa, &value, NULL))
319 goto error;
320 while (name[0])
321 {
322 log_msg_set_value(self, log_msg_get_value_handle(name), value, -1);
323 name = value = NULL;
324 if (!serialize_read_cstring(sa, &name, NULL) ||
325 !serialize_read_cstring(sa, &value, NULL))
326 goto error;
327 }
328 /* the terminating entries are not added to the hashtable, we need to free them */
329 success = TRUE;
330 error:
331 g_free(name);
332 g_free(value);
333 return success;
334 }
335
336 static gboolean
log_msg_read_sd_param(SerializeArchive * sa,gchar * sd_element_name,LogMessage * self,gboolean * has_more)337 log_msg_read_sd_param(SerializeArchive *sa, gchar *sd_element_name, LogMessage *self, gboolean *has_more)
338 {
339 gchar *name = NULL, *value = NULL;
340 gsize name_len, value_len;
341 gchar sd_param_name[256]= {0};
342 gboolean success = FALSE;
343
344 if (!serialize_read_cstring(sa, &name, &name_len) ||
345 !serialize_read_cstring(sa, &value, &value_len))
346 goto error;
347
348 if (name_len != 0 && value_len != 0)
349 {
350 strncpy(sd_param_name, sd_element_name, 256);
351 strncpy(sd_param_name + strlen(sd_element_name), name, name_len);
352 log_msg_set_value(self, log_msg_get_value_handle(sd_param_name), value, value_len);
353 *has_more = TRUE;
354 }
355 else
356 {
357 *has_more = FALSE;
358 }
359
360 success = TRUE;
361 error:
362 g_free(name);
363 g_free(value);
364 return success;
365 }
366
367 static gboolean
log_msg_read_sd_param_first(SerializeArchive * sa,gchar * sd_element_name,gsize sd_element_name_len,LogMessage * self,gboolean * has_more)368 log_msg_read_sd_param_first(SerializeArchive *sa, gchar *sd_element_name, gsize sd_element_name_len, LogMessage *self,
369 gboolean *has_more)
370 {
371 gchar *name = NULL, *value = NULL;
372 gsize name_len, value_len;
373 gchar sd_param_name[256]= {0};
374 gboolean success = FALSE;
375
376 if (!serialize_read_cstring(sa, &name, &name_len) ||
377 !serialize_read_cstring(sa, &value, &value_len))
378 goto error;
379
380 if (name_len != 0 && value_len != 0)
381 {
382 strncpy(sd_param_name, sd_element_name, sd_element_name_len);
383 strncpy(sd_param_name + strlen(sd_element_name), name, name_len);
384 log_msg_set_value(self, log_msg_get_value_handle(sd_param_name), value, value_len);
385 *has_more = TRUE;
386 }
387 else
388 {
389 *has_more = FALSE;
390 }
391 success = TRUE;
392 error:
393 g_free(name);
394 g_free(value);
395 return success;
396 }
397
398 static gboolean
log_msg_read_sd_element(SerializeArchive * sa,LogMessage * self,gboolean * has_more)399 log_msg_read_sd_element(SerializeArchive *sa, LogMessage *self, gboolean *has_more)
400 {
401 gchar *sd_id = NULL;
402 gsize sd_id_len;
403 gchar sd_element_root[66]= {0};
404 gboolean has_more_param = TRUE;
405
406 if (!serialize_read_cstring(sa, &sd_id, &sd_id_len))
407 return FALSE;
408
409 if (sd_id_len == 0)
410 {
411 *has_more=FALSE;
412 g_free(sd_id);
413 return TRUE;
414 }
415 strcpy(sd_element_root, logmsg_sd_prefix);
416 strncpy(sd_element_root + logmsg_sd_prefix_len, sd_id, sd_id_len);
417 sd_element_root[logmsg_sd_prefix_len + sd_id_len]='.';
418
419
420 if (!log_msg_read_sd_param_first(sa, sd_element_root, G_N_ELEMENTS(sd_element_root), self, &has_more_param))
421 goto error;
422
423 while (has_more_param)
424 {
425 if (!log_msg_read_sd_param(sa, sd_element_root, self, &has_more_param))
426 goto error;
427 }
428 g_free(sd_id);
429 *has_more = TRUE;
430 return TRUE;
431
432 error:
433 g_free(sd_id);
434 return FALSE;
435
436 }
437
438 static gboolean
log_msg_read_sd_data(LogMessage * self,SerializeArchive * sa)439 log_msg_read_sd_data(LogMessage *self, SerializeArchive *sa)
440 {
441 gboolean has_more_element = TRUE;
442 if (!log_msg_read_sd_element(sa, self, &has_more_element))
443 goto error;
444
445
446 while (has_more_element)
447 {
448 if (!log_msg_read_sd_element(sa, self, &has_more_element))
449 goto error;
450 }
451 return TRUE;
452 error:
453
454 return FALSE;
455 }
456
457 static gboolean
_deserialize_message_version_1x(LogMessageSerializationState * state)458 _deserialize_message_version_1x(LogMessageSerializationState *state)
459 {
460 gsize stored_len;
461 gchar *source, *pid;
462 gchar *msgid;
463
464 LogMessage *msg = state->msg;
465 SerializeArchive *sa = state->sa;
466
467 if(state->version == LGM_V10)
468 {
469 guint16 stored_flags16;
470 if (!serialize_read_uint16(sa, &stored_flags16))
471 return FALSE;
472 msg->flags = stored_flags16;
473 }
474 else
475 {
476 if (!serialize_read_uint32(sa, &msg->flags))
477 return FALSE;
478 }
479 msg->flags |= LF_STATE_MASK;
480 if (!serialize_read_uint16(sa, &msg->pri))
481 return FALSE;
482
483 if (!serialize_read_cstring(sa, &source, &stored_len))
484 return FALSE;
485 log_msg_set_value(msg, LM_V_SOURCE, source, stored_len);
486 g_free(source);
487 if (!g_sockaddr_deserialize(sa, &msg->saddr))
488 return FALSE;
489
490 if (!timestamp_deserialize_legacy(sa, msg->timestamps))
491 return FALSE;
492
493 if(state->version == LGM_V12)
494 {
495 if (!log_msg_read_tags(msg, sa))
496 return FALSE;
497 }
498 if(!log_msg_read_common_values(msg, sa))
499 return FALSE;
500 if (!serialize_read_cstring(sa, &pid, &stored_len))
501 return FALSE;
502 log_msg_set_value(msg, LM_V_PID, pid, stored_len);
503 g_free(pid);
504
505 if (!serialize_read_cstring(sa, &msgid, &stored_len))
506 return FALSE;
507 log_msg_set_value(msg, LM_V_MSGID, msgid, stored_len);
508 g_free(msgid);
509 if (!serialize_read_uint8(sa, &msg->num_matches))
510 return FALSE;
511 if(!log_msg_read_matches_details(msg, sa))
512 return FALSE;
513 if (!log_msg_read_values(msg, sa) ||
514 !log_msg_read_sd_data(msg, sa))
515 return FALSE;
516 return TRUE;
517 }
518
519 static gboolean
_check_msg_version(LogMessageSerializationState * state)520 _check_msg_version(LogMessageSerializationState *state)
521 {
522 if (!serialize_read_uint8(state->sa, &state->version))
523 return FALSE;
524
525 if (state->version < LGM_V10 || state->version > LGM_V26)
526 {
527 msg_error("Error deserializing log message, unsupported version",
528 evt_tag_int("version", state->version));
529 return FALSE;
530 }
531 return TRUE;
532 }
533
534 gboolean
log_msg_deserialize(LogMessage * self,SerializeArchive * sa)535 log_msg_deserialize(LogMessage *self, SerializeArchive *sa)
536 {
537 LogMessageSerializationState state = { 0 };
538
539 state.sa = sa;
540 state.msg = self;
541 if (!_check_msg_version(&state))
542 {
543 return FALSE;
544 }
545
546 if (state.version < LGM_V20)
547 return _deserialize_message_version_1x(&state);
548
549 return _deserialize_message_version_2x(&state);
550 }
551