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(&timestamps[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(&timestamps, 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