1 /*-
2 * Copyright 2016 Vsevolod Stakhov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #ifndef CFG_RCL_H_
17 #define CFG_RCL_H_
18
19 #include "config.h"
20 #include "cfg_file.h"
21 #include "ucl.h"
22 #include "mem_pool.h"
23
24 #define CFG_RCL_ERROR cfg_rcl_error_quark ()
25 static inline GQuark
cfg_rcl_error_quark(void)26 cfg_rcl_error_quark (void)
27 {
28 return g_quark_from_static_string ("cfg-rcl-error-quark");
29 }
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 struct rspamd_rcl_section;
36 struct rspamd_config;
37 struct rspamd_rcl_default_handler_data;
38
39 enum rspamd_rcl_flag {
40 RSPAMD_CL_FLAG_TIME_FLOAT = 0x1 << 0,
41 RSPAMD_CL_FLAG_TIME_TIMEVAL = 0x1 << 1,
42 RSPAMD_CL_FLAG_TIME_TIMESPEC = 0x1 << 2,
43 RSPAMD_CL_FLAG_TIME_INTEGER = 0x1 << 3,
44 RSPAMD_CL_FLAG_TIME_UINT_32 = 0x1 << 4,
45 RSPAMD_CL_FLAG_INT_16 = 0x1 << 5,
46 RSPAMD_CL_FLAG_INT_32 = 0x1 << 6,
47 RSPAMD_CL_FLAG_INT_64 = 0x1 << 7,
48 RSPAMD_CL_FLAG_UINT = 0x1 << 8,
49 RSPAMD_CL_FLAG_INT_SIZE = 0x1 << 9,
50 RSPAMD_CL_FLAG_STRING_PATH = 0x1 << 10,
51 RSPAMD_CL_FLAG_BOOLEAN_INVERSE = 0x1 << 11,
52 RSPAMD_CL_FLAG_STRING_LIST_HASH = 0x1 << 12,
53 RSPAMD_CL_FLAG_MULTIPLE = 0x1 << 13,
54 RSPAMD_CL_FLAG_SIGNKEY = 0x1 << 14,
55 RSPAMD_CL_FLAG_NISTKEY = 0x1 << 15,
56 };
57
58 struct rspamd_rcl_struct_parser {
59 struct rspamd_config *cfg;
60 gpointer user_struct;
61 goffset offset;
62 enum rspamd_rcl_flag flags;
63 };
64
65
66 /**
67 * Common handler type
68 * @param cfg configuration
69 * @param obj object to parse
70 * @param ud user data (depends on section)
71 * @param err error object
72 * @return TRUE if a section has been parsed
73 */
74 typedef gboolean (*rspamd_rcl_handler_t) (rspamd_mempool_t *pool,
75 const ucl_object_t *obj,
76 const gchar *key,
77 gpointer ud,
78 struct rspamd_rcl_section *section,
79 GError **err);
80
81 typedef gboolean (*rspamd_rcl_default_handler_t) (rspamd_mempool_t *pool,
82 const ucl_object_t *obj,
83 gpointer ud,
84 struct rspamd_rcl_section *section,
85 GError **err);
86
87 /**
88 * A handler type that is called at the end of section parsing
89 * @param cfg configuration
90 * @param ud user data
91 */
92 typedef void (*rspamd_rcl_section_fin_t)(rspamd_mempool_t *pool, gpointer ud);
93
94 /**
95 * Add a default handler for a section
96 * @param section section pointer
97 * @param name name of param
98 * @param handler handler of param
99 * @param offset offset in a structure
100 * @param flags flags for the parser
101 * @return newly created structure
102 */
103 struct rspamd_rcl_default_handler_data *rspamd_rcl_add_default_handler (
104 struct rspamd_rcl_section *section,
105 const gchar *name,
106 rspamd_rcl_default_handler_t handler,
107 goffset offset,
108 gint flags,
109 const gchar *doc_string);
110
111 /**
112 * Add new section to the configuration
113 * @param top top section
114 * @param name the name of the section
115 * @param key_attr name of the attribute that should be used as key attribute
116 * @param handler handler function for all attributes
117 * @param type type of object handled by a handler
118 * @param required whether at least one of these sections is required
119 * @param strict_type turn on strict check for types for this section
120 * @return newly created structure
121 */
122 struct rspamd_rcl_section *rspamd_rcl_add_section (
123 struct rspamd_rcl_section **top,
124 const gchar *name, const gchar *key_attr,
125 rspamd_rcl_handler_t handler,
126 enum ucl_type type, gboolean required, gboolean strict_type);
127
128 struct rspamd_rcl_section *rspamd_rcl_add_section_doc (
129 struct rspamd_rcl_section **top,
130 const gchar *name, const gchar *key_attr,
131 rspamd_rcl_handler_t handler,
132 enum ucl_type type, gboolean required,
133 gboolean strict_type,
134 ucl_object_t *doc_target,
135 const gchar *doc_string);
136
137 /**
138 * Init common sections known to rspamd
139 * @return top section
140 */
141 struct rspamd_rcl_section * rspamd_rcl_config_init (struct rspamd_config *cfg,
142 GHashTable *skip_sections);
143
144 /**
145 * Get a section specified by path, it understand paths separated by '/' character
146 * @param top top section
147 * @param path '/' divided path
148 * @return
149 */
150 struct rspamd_rcl_section * rspamd_rcl_config_get_section (
151 struct rspamd_rcl_section *top,
152 const char *path);
153
154 /**
155 * Parse configuration
156 * @param top top section
157 * @param cfg rspamd configuration
158 * @param ptr pointer to the target
159 * @param pool pool object
160 * @param obj ucl object to parse
161 * @param err error pointer
162 * @return
163 */
164 gboolean rspamd_rcl_parse (struct rspamd_rcl_section *top,
165 struct rspamd_config *cfg,
166 gpointer ptr, rspamd_mempool_t *pool,
167 const ucl_object_t *obj, GError **err);
168
169
170 /**
171 * Parse default structure for a section
172 * @param section section
173 * @param cfg config file
174 * @param obj object to parse
175 * @param ptr ptr to pass
176 * @param err error ptr
177 * @return TRUE if the object has been parsed
178 */
179 gboolean rspamd_rcl_section_parse_defaults (struct rspamd_config *cfg,
180 struct rspamd_rcl_section *section,
181 rspamd_mempool_t *pool, const ucl_object_t *obj, gpointer ptr,
182 GError **err);
183 /**
184 * Here is a section of common handlers that accepts rcl_struct_parser
185 * which itself contains a struct pointer and the offset of a member in a
186 * specific structure
187 */
188
189 /**
190 * Parse a string field of a structure
191 * @param cfg config pointer
192 * @param obj object to parse
193 * @param ud struct_parser structure
194 * @param section the current section
195 * @param err error pointer
196 * @return TRUE if a string value has been successfully parsed
197 */
198 gboolean rspamd_rcl_parse_struct_string (rspamd_mempool_t *pool,
199 const ucl_object_t *obj,
200 gpointer ud,
201 struct rspamd_rcl_section *section,
202 GError **err);
203
204 /**
205 * Parse an integer field of a structure
206 * @param cfg config pointer
207 * @param obj object to parse
208 * @param ud struct_parser structure
209 * @param section the current section
210 * @param err error pointer
211 * @return TRUE if a value has been successfully parsed
212 */
213 gboolean rspamd_rcl_parse_struct_integer (rspamd_mempool_t *pool,
214 const ucl_object_t *obj,
215 gpointer ud,
216 struct rspamd_rcl_section *section,
217 GError **err);
218
219
220 /**
221 * Parse a float field of a structure
222 * @param cfg config pointer
223 * @param obj object to parse
224 * @param ud struct_parser structure
225 * @param section the current section
226 * @param err error pointer
227 * @return TRUE if a value has been successfully parsed
228 */
229 gboolean rspamd_rcl_parse_struct_double (rspamd_mempool_t *pool,
230 const ucl_object_t *obj,
231 gpointer ud,
232 struct rspamd_rcl_section *section,
233 GError **err);
234
235 /**
236 * Parse a time field of a structure
237 * @param cfg config pointer
238 * @param obj object to parse
239 * @param ud struct_parser structure (flags mean the exact structure used)
240 * @param section the current section
241 * @param err error pointer
242 * @return TRUE if a value has been successfully parsed
243 */
244 gboolean rspamd_rcl_parse_struct_time (rspamd_mempool_t *pool,
245 const ucl_object_t *obj,
246 gpointer ud,
247 struct rspamd_rcl_section *section,
248 GError **err);
249
250 /**
251 * Parse a string list field of a structure presented by a GList* object
252 * @param cfg config pointer
253 * @param obj object to parse
254 * @param ud struct_parser structure (flags mean the exact structure used)
255 * @param section the current section
256 * @param err error pointer
257 * @return TRUE if a value has been successfully parsed
258 */
259 gboolean rspamd_rcl_parse_struct_string_list (rspamd_mempool_t *pool,
260 const ucl_object_t *obj,
261 gpointer ud,
262 struct rspamd_rcl_section *section,
263 GError **err);
264
265 /**
266 * Parse a boolean field of a structure
267 * @param cfg config pointer
268 * @param obj object to parse
269 * @param ud struct_parser structure (flags mean the exact structure used)
270 * @param section the current section
271 * @param err error pointer
272 * @return TRUE if a value has been successfully parsed
273 */
274 gboolean rspamd_rcl_parse_struct_boolean (rspamd_mempool_t *pool,
275 const ucl_object_t *obj,
276 gpointer ud,
277 struct rspamd_rcl_section *section,
278 GError **err);
279
280 /**
281 * Parse a keypair field of a structure
282 * @param cfg config pointer
283 * @param obj object to parse
284 * @param ud struct_parser structure (flags mean the exact structure used)
285 * @param section the current section
286 * @param err error pointer
287 * @return TRUE if a value has been successfully parsed
288 */
289 gboolean rspamd_rcl_parse_struct_keypair (rspamd_mempool_t *pool,
290 const ucl_object_t *obj,
291 gpointer ud,
292 struct rspamd_rcl_section *section,
293 GError **err);
294
295 /**
296 * Parse a pubkey field of a structure
297 * @param cfg config pointer
298 * @param obj object to parse
299 * @param ud struct_parser structure (flags mean the exact structure used)
300 * @param section the current section
301 * @param err error pointer
302 * @return TRUE if a value has been successfully parsed
303 */
304 gboolean rspamd_rcl_parse_struct_pubkey (rspamd_mempool_t *pool,
305 const ucl_object_t *obj,
306 gpointer ud,
307 struct rspamd_rcl_section *section,
308 GError **err);
309
310 /**
311 * Parse a inet addr field of a structure
312 * @param cfg config pointer
313 * @param obj object to parse
314 * @param ud struct_parser structure (flags mean the exact structure used)
315 * @param section the current section
316 * @param err error pointer
317 * @return TRUE if a value has been successfully parsed
318 */
319 gboolean rspamd_rcl_parse_struct_addr (rspamd_mempool_t *pool,
320 const ucl_object_t *obj,
321 gpointer ud,
322 struct rspamd_rcl_section *section,
323 GError **err);
324
325 /**
326 * Parse a gmime inet address field of a structure
327 * @param cfg config pointer
328 * @param obj object to parse
329 * @param ud struct_parser structure (flags mean the exact structure used)
330 * @param section the current section
331 * @param err error pointer
332 * @return TRUE if a value has been successfully parsed
333 */
334 gboolean rspamd_rcl_parse_struct_mime_addr (rspamd_mempool_t *pool,
335 const ucl_object_t *obj,
336 gpointer ud,
337 struct rspamd_rcl_section *section,
338 GError **err);
339
340 /**
341 * Parse a raw ucl object
342 * @param cfg config pointer
343 * @param obj object to parse
344 * @param ud struct_parser structure (flags mean the exact structure used)
345 * @param section the current section
346 * @param err error pointer
347 * @return TRUE if a value has been successfully parsed
348 */
349 gboolean rspamd_rcl_parse_struct_ucl (rspamd_mempool_t *pool,
350 const ucl_object_t *obj,
351 gpointer ud,
352 struct rspamd_rcl_section *section,
353 GError **err);
354
355
356 /**
357 * Utility functions
358 */
359
360 /**
361 * Register new parser for a worker type of an option with the specified name
362 * @param cfg config structure
363 * @param type type of worker (GQuark)
364 * @param name name of option
365 * @param handler handler of option
366 * @param target opaque target structure
367 * @param offset offset inside a structure
368 */
369 void rspamd_rcl_register_worker_option (struct rspamd_config *cfg,
370 GQuark type,
371 const gchar *name,
372 rspamd_rcl_default_handler_t handler,
373 gpointer target,
374 glong offset,
375 gint flags,
376 const gchar *doc_string);
377
378 /**
379 * Register a default parser for a worker
380 * @param cfg config structure
381 * @param type type of worker (GQuark)
382 * @param func handler function
383 * @param ud userdata for handler function
384 */
385 void rspamd_rcl_register_worker_parser (struct rspamd_config *cfg, gint type,
386 gboolean (*func)(ucl_object_t *, gpointer), gpointer ud);
387
388 /**
389 * Adds new documentation object to the configuration
390 * @param doc_target target object where to insert documentation (top object is used if this is NULL)
391 * @param doc_object documentation object to insert
392 */
393 ucl_object_t *rspamd_rcl_add_doc_obj (ucl_object_t *doc_target,
394 const char *doc_string,
395 const char *doc_name,
396 ucl_type_t type,
397 rspamd_rcl_default_handler_t handler,
398 gint flags,
399 const char *default_value,
400 gboolean required);
401
402 /**
403 * Adds new documentation option specified by path `doc_path` that should be
404 * split by dots
405 */
406 ucl_object_t *rspamd_rcl_add_doc_by_path (struct rspamd_config *cfg,
407 const gchar *doc_path,
408 const char *doc_string,
409 const char *doc_name,
410 ucl_type_t type,
411 rspamd_rcl_default_handler_t handler,
412 gint flags,
413 const char *default_value,
414 gboolean required);
415
416
417 /**
418 * Parses example and adds documentation according to the example:
419 *
420 * ```
421 * section {
422 * param1 = value; # explanation
423 * param2 = value; # explanation
424 * }
425 * ```
426 *
427 * will produce the following documentation strings:
428 * section ->
429 * section.param1 : explanation
430 * section.param2 : explanation
431 *
432 * @param cfg
433 * @param root_path
434 * @param example_data
435 * @param example_len
436 * @return
437 */
438 ucl_object_t *rspamd_rcl_add_doc_by_example (struct rspamd_config *cfg,
439 const gchar *root_path,
440 const gchar *doc_string,
441 const gchar *doc_name,
442 const gchar *example_data, gsize example_len);
443
444 /**
445 * Add lua modules path
446 * @param cfg
447 * @param path
448 * @param err
449 * @return
450 */
451 gboolean rspamd_rcl_add_lua_plugins_path (struct rspamd_config *cfg,
452 const gchar *path,
453 gboolean main_path,
454 GHashTable *modules_seen,
455 GError **err);
456
457
458 /**
459 * Calls for an external lua function to apply potential config transformations
460 * if needed. This function can change the cfg->rcl_obj.
461 *
462 * Example of transformation function:
463 *
464 * function(obj)
465 * if obj.something == 'foo' then
466 * obj.something = "bla"
467 * return true, obj
468 * end
469 *
470 * return false, nil
471 * end
472 *
473 * If function returns 'false' then rcl_obj is not touched. Otherwise,
474 * it is changed, then rcl_obj is imported from lua. Old config is dereferenced.
475 * @param cfg
476 */
477 void rspamd_rcl_maybe_apply_lua_transform (struct rspamd_config *cfg);
478 void rspamd_rcl_section_free (gpointer p);
479
480 void rspamd_config_calculate_cksum (struct rspamd_config *cfg);
481
482 /*
483 * Read configuration file
484 */
485 gboolean rspamd_config_parse_ucl (struct rspamd_config *cfg,
486 const gchar *filename,
487 GHashTable *vars,
488 ucl_include_trace_func_t inc_trace,
489 void *trace_data,
490 gboolean skip_jinja,
491 GError **err);
492 gboolean rspamd_config_read (struct rspamd_config *cfg,
493 const gchar *filename,
494 rspamd_rcl_section_fin_t logger_fin,
495 gpointer logger_ud,
496 GHashTable *vars,
497 gboolean skip_jinja,
498 gchar **lua_env);
499
500 #ifdef __cplusplus
501 }
502 #endif
503
504 #endif /* CFG_RCL_H_ */
505