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