1 /*
2  * Copyright (c) 2002-2015 Balabit
3  * Copyright (c) 1998-2012 Balázs Scheidler
4  * Copyright (c) 2012-2015 Viktor Juhasz <viktor.juhasz@balabit.com>
5  * Copyright (c) 2012-2013 Viktor Tusa
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  * As an additional exemption you are allowed to compile & link against the
22  * OpenSSL libraries as published by the OpenSSL project. See the file
23  * COPYING for details.
24  *
25  */
26 
27 #include "logmsg/nvtable-serialize.h"
28 #include "logmsg/nvtable-serialize-endianutils.h"
29 #include "logmsg/logmsg.h"
30 #include "messages.h"
31 
32 #include <stdlib.h>
33 #include <string.h>
34 
35 
36 typedef struct _NVTableMetaData
37 {
38   guint32 magic;
39   guint8 flags;
40 } NVTableMetaData;
41 
42 /**********************************************************************
43  * deserialize an NVTable
44  **********************************************************************/
45 
46 static gboolean
_deserialize_static_entries(SerializeArchive * sa,NVTable * res)47 _deserialize_static_entries(SerializeArchive *sa, NVTable *res)
48 {
49   if (!serialize_read_uint32_array(sa, res->static_entries, res->num_static_entries))
50     return FALSE;
51   return TRUE;
52 }
53 
54 static gboolean
_deserialize_dynamic_entries(SerializeArchive * sa,NVTable * res)55 _deserialize_dynamic_entries(SerializeArchive *sa, NVTable *res)
56 {
57   NVIndexEntry *index_table;
58 
59   index_table = nv_table_get_index(res);
60   if (!serialize_read_uint32_array(sa, (guint32 *) index_table, res->index_size * 2))
61     return FALSE;
62   return TRUE;
63 }
64 
65 static gboolean
_read_struct(SerializeArchive * sa,NVTable * res)66 _read_struct(SerializeArchive *sa, NVTable *res)
67 {
68   return _deserialize_static_entries(sa, res) && _deserialize_dynamic_entries(sa, res);
69 }
70 
71 static gboolean
_has_to_swap_bytes(guint8 flags)72 _has_to_swap_bytes(guint8 flags)
73 {
74   return !!(flags & NVT_SF_BE) != (G_BYTE_ORDER == G_BIG_ENDIAN);
75 }
76 
77 static inline gboolean
_read_magic(SerializeArchive * sa,guint32 * magic)78 _read_magic(SerializeArchive *sa, guint32 *magic)
79 {
80   return serialize_read_uint32(sa, magic);
81 }
82 
83 static inline gboolean
_read_flags(SerializeArchive * sa,guint8 * flags)84 _read_flags(SerializeArchive *sa, guint8 *flags)
85 {
86   return serialize_read_uint8(sa, flags);
87 }
88 
89 static inline gboolean
_read_metadata(SerializeArchive * sa,NVTableMetaData * meta_data)90 _read_metadata(SerializeArchive *sa, NVTableMetaData *meta_data)
91 {
92   if (!_read_magic(sa, &meta_data->magic))
93     {
94       return FALSE;
95     }
96 
97   if (!_read_flags(sa, &meta_data->flags))
98     {
99       return FALSE;
100     }
101 
102   if (_has_to_swap_bytes(meta_data->flags))
103     {
104       meta_data->magic = GUINT32_SWAP_LE_BE(meta_data->magic);
105     }
106 
107   if (memcmp((void *)&meta_data->magic, (const void *)NV_TABLE_MAGIC_V2, 4) != 0)
108     {
109       return FALSE;
110     }
111   return TRUE;
112 }
113 
114 static gboolean
_read_header(SerializeArchive * sa,NVTable ** nvtable)115 _read_header(SerializeArchive *sa, NVTable **nvtable)
116 {
117   NVTable *res = NULL;
118   guint32 size;
119 
120   g_assert(*nvtable == NULL);
121 
122   if (!serialize_read_uint32(sa, &size))
123     goto error;
124 
125   if (size > NV_TABLE_MAX_BYTES)
126     goto error;
127 
128   res = (NVTable *) g_malloc(size);
129   res->size = size;
130 
131   if (!serialize_read_uint32(sa, &res->used))
132     goto error;
133 
134   if (!serialize_read_uint16(sa, &res->index_size))
135     goto error;
136 
137   if (!serialize_read_uint8(sa, &res->num_static_entries))
138     goto error;
139 
140   /* static entries has to be known by this syslog-ng, if they are over
141    * LM_V_MAX, that means we have no clue how an entry is called, as static
142    * entries don't contain names.  If there are less static entries, that
143    * can be ok. */
144 
145   if (res->num_static_entries > LM_V_MAX)
146     goto error;
147 
148   /* validates self->used and self->index_size value as compared to "size" */
149   if (!nv_table_alloc_check(res, 0))
150     goto error;
151 
152   res->borrowed = FALSE;
153   res->ref_cnt = 1;
154   *nvtable = res;
155   return TRUE;
156 
157 error:
158   if (res)
159     g_free(res);
160   return FALSE;
161 }
162 
163 static inline gboolean
_read_payload(SerializeArchive * sa,NVTable * res)164 _read_payload(SerializeArchive *sa, NVTable *res)
165 {
166   return serialize_read_blob(sa, NV_TABLE_ADDR(res, res->size - res->used), res->used);
167 }
168 
169 NVTable *
nv_table_deserialize(LogMessageSerializationState * state)170 nv_table_deserialize(LogMessageSerializationState *state)
171 {
172   SerializeArchive *sa = state->sa;
173   NVTableMetaData meta_data;
174   NVTable *res = NULL;
175 
176   if (!_read_metadata(sa, &meta_data))
177     goto error;
178 
179   if (!_read_header(sa, &res))
180     goto error;
181 
182   state->nvtable_flags = meta_data.flags;
183   state->nvtable = res;
184   if (!_read_struct(sa, res))
185     goto error;
186 
187   if (!_read_payload(sa, res))
188     goto error;
189 
190   if (_has_to_swap_bytes(meta_data.flags))
191     nv_table_data_swap_bytes(res);
192 
193 
194   return res;
195 
196 error:
197   if (res)
198     g_free(res);
199   return NULL;
200 }
201 
202 /**********************************************************************
203  * serialize an NVTable
204  **********************************************************************/
205 
206 static void
_write_struct(SerializeArchive * sa,NVTable * self)207 _write_struct(SerializeArchive *sa, NVTable *self)
208 {
209   serialize_write_uint32(sa, self->size);
210   serialize_write_uint32(sa, self->used);
211   serialize_write_uint16(sa, self->index_size);
212   serialize_write_uint8(sa, self->num_static_entries);
213   serialize_write_uint32_array(sa, self->static_entries, self->num_static_entries);
214   serialize_write_uint32_array(sa, (guint32 *) nv_table_get_index(self), self->index_size * 2);
215 }
216 
217 static void
_write_meta_data(SerializeArchive * sa,NVTableMetaData * meta_data)218 _write_meta_data(SerializeArchive *sa, NVTableMetaData *meta_data)
219 {
220   serialize_write_uint32(sa, meta_data->magic);
221   serialize_write_uint8(sa, meta_data->flags);
222 }
223 
224 static void
_fill_meta_data(NVTable * self,NVTableMetaData * meta_data)225 _fill_meta_data(NVTable *self, NVTableMetaData *meta_data)
226 {
227   memcpy((void *)&meta_data->magic, (const void *) NV_TABLE_MAGIC_V2, 4);
228   if (G_BYTE_ORDER == G_BIG_ENDIAN)
229     meta_data->flags |= NVT_SF_BE;
230   meta_data->flags |= NVT_SUPPORTS_UNSET;
231 }
232 
233 static void
_write_payload(SerializeArchive * sa,NVTable * self)234 _write_payload(SerializeArchive *sa, NVTable *self)
235 {
236   serialize_write_blob(sa, NV_TABLE_ADDR(self, self->size - self->used), self->used);
237 }
238 
239 gboolean
nv_table_serialize(LogMessageSerializationState * state,NVTable * self)240 nv_table_serialize(LogMessageSerializationState *state, NVTable *self)
241 {
242   NVTableMetaData meta_data = { 0 };
243   SerializeArchive *sa = state->sa;
244 
245   _fill_meta_data(self, &meta_data);
246   _write_meta_data(sa, &meta_data);
247 
248   _write_struct(sa, self);
249 
250   _write_payload(sa, self);
251   return TRUE;
252 }
253