Coverage Report

Created: 2025-08-26 07:01

/src/dovecot/src/lib-settings/settings-parser.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef SETTINGS_PARSER_H
2
#define SETTINGS_PARSER_H
3
4
#include "str-parse.h"
5
6
struct stat;
7
struct var_expand_table;
8
struct var_expand_provider;
9
10
0
#define SETTINGS_SEPARATOR '/'
11
#define SETTINGS_SEPARATOR_S "/"
12
13
0
#define SETTINGS_FILTER_ARRAY_SEPARATORS ",\t "
14
15
/* These values are shown as "unlimited" */
16
0
#define SET_VALUE_UNLIMITED "unlimited"
17
0
#define SET_UINT_UNLIMITED UINT_MAX
18
0
#define SET_SIZE_UNLIMITED UOFF_T_MAX
19
20
/* These values are shown as "infinite" */
21
0
#define SET_VALUE_INFINITE "infinite"
22
0
#define SET_TIME_INFINITE UINT_MAX
23
0
#define SET_TIME_MSECS_INFINITE UINT_MAX
24
25
0
#define SET_LIST_APPEND "+"
26
0
#define SET_LIST_REPLACE "$"
27
0
#define SET_LIST_CLEAR "."
28
29
#define SET_FILE_INLINE_PREFIX "inline:"
30
31
enum setting_type {
32
  SET_BOOL,
33
  SET_UINTMAX,
34
  SET_UINT,
35
  SET_UINT_OCT,
36
  SET_TIME,
37
  SET_TIME_MSECS,
38
  SET_SIZE,
39
  SET_IN_PORT, /* internet port */
40
  SET_STR, /* string with %variables */
41
  SET_STR_NOVARS, /* string explicitly without %variables */
42
  SET_ENUM,
43
  SET_FILE, /* string: <path> [<LF> file contents] */
44
  SET_STRLIST, /* of type ARRAY_TYPE(const_string) */
45
  SET_BOOLLIST, /* of type ARRAY_TYPE(const_string) - guaranteed NULL-terminated */
46
  SET_ALIAS, /* alias name for above setting definition */
47
  SET_FILTER_NAME,
48
  SET_FILTER_ARRAY,
49
};
50
enum setting_flags {
51
  SET_FLAG_HIDDEN = BIT(0),
52
  /* Used only for SETTING_DEFINE_LIST_END */
53
  SET_FLAG_EOL = BIT(1),
54
};
55
56
enum setting_apply_flags {
57
  /* Used when applying override settings (e.g. userdb or -o parameter) */
58
  SETTING_APPLY_FLAG_OVERRIDE = BIT(0),
59
  /* SETTINGS_GET_FLAG_NO_EXPAND is being used. */
60
  SETTING_APPLY_FLAG_NO_EXPAND = BIT(1),
61
};
62
63
#define SETTING_DEFINE_LIST_END { 0, SET_FLAG_EOL, NULL, 0, NULL, NULL, NULL }
64
65
struct setting_filter_array_order {
66
  const struct setting_parser_info *info;
67
  const char *field_name;
68
  bool reverse;
69
};
70
71
struct setting_define {
72
  enum setting_type type;
73
  enum setting_flags flags;
74
  const char *key;
75
76
  size_t offset;
77
  const char *filter_array_field_name;
78
  const struct setting_filter_array_order *filter_array_order;
79
  const char *required_setting;
80
};
81
82
#define SETTING_DEFINE_STRUCT_TYPE(_enum_type, _flags, _c_type, _key, _name, _struct_name) \
83
  { .type = (_enum_type) + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \
84
    ((_struct_name *)0)->_name, _c_type), \
85
    .flags = _flags, .key = _key, \
86
    .offset = offsetof(_struct_name, _name) }
87
88
#define SETTING_DEFINE_STRUCT_BOOL(key, name, struct_name) \
89
  SETTING_DEFINE_STRUCT_TYPE(SET_BOOL, 0, bool, key, name, struct_name)
90
#define SETTING_DEFINE_STRUCT_UINTMAX(key, name, struct_name) \
91
  SETTING_DEFINE_STRUCT_TYPE(SET_UINTMAX, 0, uintmax_t, key, name, struct_name)
92
#define SETTING_DEFINE_STRUCT_UINT(key, name, struct_name) \
93
  SETTING_DEFINE_STRUCT_TYPE(SET_UINT, 0, unsigned int, key, name, struct_name)
94
#define SETTING_DEFINE_STRUCT_UINT_OCT(key, name, struct_name) \
95
  SETTING_DEFINE_STRUCT_TYPE(SET_UINT_OCT, 0, unsigned int, key, name, struct_name)
96
#define SETTING_DEFINE_STRUCT_TIME(key, name, struct_name) \
97
  SETTING_DEFINE_STRUCT_TYPE(SET_TIME, 0, unsigned int, key, name, struct_name)
98
#define SETTING_DEFINE_STRUCT_TIME_MSECS(key, name, struct_name) \
99
  SETTING_DEFINE_STRUCT_TYPE(SET_TIME_MSECS, 0, unsigned int, key, name, struct_name)
100
#define SETTING_DEFINE_STRUCT_SIZE(key, name, struct_name) \
101
  SETTING_DEFINE_STRUCT_TYPE(SET_SIZE, 0, uoff_t, key, name, struct_name)
102
#define SETTING_DEFINE_STRUCT_IN_PORT(key, name, struct_name) \
103
  SETTING_DEFINE_STRUCT_TYPE(SET_IN_PORT, 0, in_port_t, key, name, struct_name)
104
#define SETTING_DEFINE_STRUCT_STR(key, name, struct_name) \
105
  SETTING_DEFINE_STRUCT_TYPE(SET_STR, 0, const char *, key, name, struct_name)
106
#define SETTING_DEFINE_STRUCT_STR_NOVARS(key, name, struct_name) \
107
  SETTING_DEFINE_STRUCT_TYPE(SET_STR_NOVARS, 0, const char *, key, name, struct_name)
108
#define SETTING_DEFINE_STRUCT_ENUM(key, name, struct_name) \
109
  SETTING_DEFINE_STRUCT_TYPE(SET_ENUM, 0, const char *, key, name, struct_name)
110
#define SETTING_DEFINE_STRUCT_FILE(key, name, struct_name) \
111
  SETTING_DEFINE_STRUCT_TYPE(SET_FILE, 0, const char *, key, name, struct_name)
112
#define SETTING_DEFINE_STRUCT_BOOLLIST(key, name, struct_name) \
113
  SETTING_DEFINE_STRUCT_TYPE(SET_BOOLLIST, 0, ARRAY_TYPE(const_string), key, name, struct_name)
114
#define SETTING_DEFINE_STRUCT_STRLIST(key, name, struct_name) \
115
  SETTING_DEFINE_STRUCT_TYPE(SET_STRLIST, 0, ARRAY_TYPE(const_string), key, name, struct_name)
116
117
#define SETTING_DEFINE_STRUCT_BOOL_HIDDEN(key, name, struct_name) \
118
  SETTING_DEFINE_STRUCT_TYPE(SET_BOOL, SET_FLAG_HIDDEN, bool, key, name, struct_name)
119
#define SETTING_DEFINE_STRUCT_UINTMAX_HIDDEN(key, name, struct_name) \
120
  SETTING_DEFINE_STRUCT_TYPE(SET_UINTMAX, SET_FLAG_HIDDEN, uintmax_t, key, name, struct_name)
121
#define SETTING_DEFINE_STRUCT_UINT_HIDDEN(key, name, struct_name) \
122
  SETTING_DEFINE_STRUCT_TYPE(SET_UINT, SET_FLAG_HIDDEN, unsigned int, key, name, struct_name)
123
#define SETTING_DEFINE_STRUCT_UINT_OCT_HIDDEN(key, name, struct_name) \
124
  SETTING_DEFINE_STRUCT_TYPE(SET_UINT_OCT, SET_FLAG_HIDDEN, unsigned int, key, name, struct_name)
125
#define SETTING_DEFINE_STRUCT_TIME_HIDDEN(key, name, struct_name) \
126
  SETTING_DEFINE_STRUCT_TYPE(SET_TIME, SET_FLAG_HIDDEN, unsigned int, key, name, struct_name)
127
#define SETTING_DEFINE_STRUCT_TIME_MSECS_HIDDEN(key, name, struct_name) \
128
  SETTING_DEFINE_STRUCT_TYPE(SET_TIME_MSECS, SET_FLAG_HIDDEN, unsigned int, key, name, struct_name)
129
#define SETTING_DEFINE_STRUCT_SIZE_HIDDEN(key, name, struct_name) \
130
  SETTING_DEFINE_STRUCT_TYPE(SET_SIZE, SET_FLAG_HIDDEN, uoff_t, key, name, struct_name)
131
#define SETTING_DEFINE_STRUCT_IN_PORT_HIDDEN(key, name, struct_name) \
132
  SETTING_DEFINE_STRUCT_TYPE(SET_IN_PORT, SET_FLAG_HIDDEN, in_port_t, key, name, struct_name)
133
#define SETTING_DEFINE_STRUCT_STR_HIDDEN(key, name, struct_name) \
134
  SETTING_DEFINE_STRUCT_TYPE(SET_STR, SET_FLAG_HIDDEN, const char *, key, name, struct_name)
135
#define SETTING_DEFINE_STRUCT_STR_NOVARS_HIDDEN(key, name, struct_name) \
136
  SETTING_DEFINE_STRUCT_TYPE(SET_STR_NOVARS, SET_FLAG_HIDDEN, const char *, key, name, struct_name)
137
#define SETTING_DEFINE_STRUCT_ENUM_HIDDEN(key, name, struct_name) \
138
  SETTING_DEFINE_STRUCT_TYPE(SET_ENUM, SET_FLAG_HIDDEN, const char *, key, name, struct_name)
139
#define SETTING_DEFINE_STRUCT_FILE_HIDDEN(key, name, struct_name) \
140
  SETTING_DEFINE_STRUCT_TYPE(SET_FILE, SET_FLAG_HIDDEN, const char *, key, name, struct_name)
141
#define SETTING_DEFINE_STRUCT_BOOLLIST_HIDDEN(key, name, struct_name) \
142
  SETTING_DEFINE_STRUCT_TYPE(SET_BOOLLIST, SET_FLAG_HIDDEN, ARRAY_TYPE(const_string), key, name, struct_name)
143
#define SETTING_DEFINE_STRUCT_STRLIST_HIDDEN(key, name, struct_name) \
144
  SETTING_DEFINE_STRUCT_TYPE(SET_STRLIST, SET_FLAG_HIDDEN, ARRAY_TYPE(const_string), key, name, struct_name)
145
146
struct settings_file {
147
  /* Path to the file. May be "" if the content is inlined. */
148
  const char *path;
149
  /* File contents - always available. NULs inside the file are not
150
     supported. */
151
  const char *content;
152
};
153
154
struct setting_keyvalue {
155
  const char *key;
156
  const char *value;
157
};
158
159
struct setting_parser_info {
160
  /* Unique name for the settings struct */
161
  const char *name;
162
  /* If non-NULL, config process verifies whether this plugin actually
163
     exists on filesystem before exposing these settings. This allows
164
     for example the plugins in Dovecot core to be extracted into
165
     separate optional packages, even though they don't have individual
166
     settings plugins. */
167
  const char *plugin_dependency;
168
169
  const struct setting_define *defines;
170
  const void *defaults;
171
  /* Add defaults via strings on top of the of defaults struct. */
172
  const struct setting_keyvalue *default_settings;
173
174
  size_t struct_size;
175
  size_t pool_offset1; /* 1 + offset to pool_t field */
176
177
  /* This is called for every setting that is parsed. *value is already
178
     the final pointer stored into the settings struct. If it's modified,
179
     it should usually be allocated from set->pool. */
180
  bool (*setting_apply)(struct event *event, void *set,
181
            const char *key, const char **value,
182
            enum setting_apply_flags flags, const char **error_r);
183
  /* This is called after %variable expansion. */
184
  bool (*check_func)(void *set, pool_t pool, const char **error_r);
185
  /* The event parameter can be used with settings_get*() to access other
186
     settings structs. */
187
  bool (*ext_check_func)(struct event *event, void *set, pool_t pool, const char **error_r);
188
189
};
190
ARRAY_DEFINE_TYPE(setting_parser_info, struct setting_parser_info);
191
192
enum settings_parser_flags {
193
  SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS  = 0x01,
194
  /* Filters are added in reverse order. New filters are inserted to the
195
     beginning of the array. */
196
  SETTINGS_PARSER_FLAG_INSERT_FILTERS   = 0x04,
197
};
198
199
enum settings_binary {
200
  SETTINGS_BINARY_OTHER,
201
  SETTINGS_BINARY_CONFIG,
202
  SETTINGS_BINARY_DOVECONF
203
};
204
205
struct setting_parser_context;
206
207
/* If a string setting value has this pointer, it means the setting isn't
208
   actually known because it contained %{variables}. [ext_]check_func() can use
209
   this to not give early errors when the variable value isn't known. */
210
extern const char *set_value_unknown;
211
212
/* This is set for ext_check_func(event) when config binary checking settings.
213
   In this case for example %variables aren't expanded, so ext_check_func()
214
   shouldn't fail if it does further settings_get*() calls that fail. */
215
#define SETTINGS_EVENT_NO_EXPAND "settings_event_no_expand"
216
217
struct setting_parser_context *
218
settings_parser_init(pool_t set_pool, const struct setting_parser_info *root,
219
         enum settings_parser_flags flags);
220
void settings_parser_ref(struct setting_parser_context *ctx);
221
void settings_parser_unref(struct setting_parser_context **ctx);
222
223
/* Returns number of defines in info->defines */
224
unsigned int
225
setting_parser_info_get_define_count(const struct setting_parser_info *info);
226
/* Find a specific key from info and return its index number in the defines
227
   array. "list/key" will return the list's define. If the key is an
228
   alias, the primary key's index is returned. */
229
bool setting_parser_info_find_key(const struct setting_parser_info *info,
230
          const char *key, unsigned int *idx_r);
231
232
/* Returns the current settings. */
233
void *settings_parser_get_set(const struct setting_parser_context *ctx);
234
235
/* Return the last error. */
236
const char *settings_parser_get_error(struct setting_parser_context *ctx);
237
238
/* Returns pointer to value for a key, or NULL if not found. */
239
const void *
240
settings_parse_get_value(struct setting_parser_context *ctx,
241
       const char **key, enum setting_type *type_r);
242
/* Parse key/value pair. Returns 1 if OK, 0 if key is unknown, -1 if error. */
243
int settings_parse_keyvalue(struct setting_parser_context *ctx,
244
          const char *key, const char *value);
245
/* Parse key index/value pair. The key_idx points to the key in
246
   info->defines[]. The key string is still needed to support lists, which
247
   need the key in "list/key" format. Returns 0 if OK, -1 if error. */
248
int settings_parse_keyidx_value(struct setting_parser_context *ctx,
249
        unsigned int key_idx, const char *key,
250
        const char *value);
251
/* Same as settings_parse_keyvalue(), but don't strdup() the value. The value
252
   pointer's validity must be enforced by the caller. */
253
int settings_parse_keyvalue_nodup(struct setting_parser_context *ctx,
254
          const char *key, const char *value);
255
/* Same as settings_parse_keyidx_value(), but don't strdup() the value.
256
   The value pointer's validity must be enforced by the caller. */
257
int settings_parse_keyidx_value_nodup(struct setting_parser_context *ctx,
258
              unsigned int key_idx, const char *key,
259
              const char *value);
260
/* Ignore any further attempts to add to the named list filter or boollist. */
261
void settings_parse_array_stop(struct setting_parser_context *ctx,
262
             unsigned int key_idx);
263
/* Returns TRUE if list has the specific key. The key must NOT include the
264
   list/ prefix. */
265
bool settings_parse_list_has_key(struct setting_parser_context *ctx,
266
         unsigned int key_idx,
267
         const char *key_suffix);
268
/* Call all check_func()s and ext_check_func()s to see if currently parsed
269
   settings are valid. */
270
bool settings_parser_check(struct setting_parser_context *ctx, pool_t pool,
271
         struct event *event, const char **error_r);
272
bool settings_check(struct event *event, const struct setting_parser_info *info,
273
        pool_t pool, void *set, const char **error_r);
274
275
/* Read a SET_FILE from the given path and write
276
   "<prefix><value_path>\n<contents>" to output_r. Returns 0 on success,
277
   -1 on error. */
278
int settings_parse_read_file(const char *path, const char *value_path,
279
           pool_t pool, struct stat *st_r,
280
           const char *prefix, const char **output_r,
281
           const char **error_r);
282
int settings_parse_boollist_string(const char *value, pool_t pool,
283
           ARRAY_TYPE(const_string) *dest,
284
           const char **error_r);
285
/* Returns the boollist array NULL-terminated. The list is actually always
286
   already NULL-terminated, but to avoid confusion with regular non-NULL
287
   terminated arrays, use this function instead. Also, it includes some sanity
288
   checks to try to make sure it's used only for boollists. */
289
const char *const *settings_boollist_get(const ARRAY_TYPE(const_string) *array);
290
/* Finish array into a boollist type by adding NULL-termination and optional
291
   stop flag. If stop=TRUE, this indicates that the boollist replaces the full
292
   list instead of adding to it. The boollist can still be updated afterwards,
293
   as long as this function is called again after modifications. */
294
void settings_boollist_finish(ARRAY_TYPE(const_string) *array, bool stop);
295
296
/* Checks if boollist is marked as replacing the full list */
297
bool settings_boollist_is_stopped(const ARRAY_TYPE(const_string) *array);
298
/* Split the settings value into path and content. The path is allocated from
299
   the path_pool, while content points directly to the value string. */
300
void settings_file_get(const char *value, pool_t path_pool,
301
           struct settings_file *file_r);
302
/* Returns TRUE if the settings value contains a non-empty path. The value
303
   is expected to be in the SET_FILE format (path LF content). */
304
bool settings_file_has_path(const char *value);
305
/* Convert settings_file into a value (path LF content). The file path may be
306
   NULL, but the content must exist. */
307
const char *settings_file_get_value(pool_t pool,
308
            const struct settings_file *file);
309
310
/* Return hash of all the settings, except the specified fields
311
   (NULL = no exceptions). */
312
unsigned int settings_hash(const struct setting_parser_info *info,
313
         const void *set, const char *const *except_fields);
314
/* Returns TRUE if the two settings structs are equal, except for the
315
   specified fields (NULL = no exceptions). */
316
bool settings_equal(const struct setting_parser_info *info,
317
        const void *set1, const void *set2,
318
        const char *const *except_fields);
319
320
/* Allocate a new instance of a settings struct filled with the default
321
   settings. */
322
void *settings_defaults_dup(pool_t pool, const struct setting_parser_info *info);
323
324
/* Return section name escaped */
325
const char *settings_section_escape(const char *name);
326
const char *settings_section_unescape(const char *name);
327
328
static inline bool settings_value_is_unlimited(const char *value)
329
0
{
330
  /* allow both as input for all types */
331
0
  return strcmp(value, SET_VALUE_UNLIMITED) == 0 ||
332
0
    strcmp(value, SET_VALUE_INFINITE) == 0;
333
0
}
Unexecuted instantiation: smtp-server-connection.c:settings_value_is_unlimited
Unexecuted instantiation: smtp-server.c:settings_value_is_unlimited
Unexecuted instantiation: smtp-server-cmd-starttls.c:settings_value_is_unlimited
Unexecuted instantiation: iostream-ssl.c:settings_value_is_unlimited
Unexecuted instantiation: iostream-ssl-context-cache.c:settings_value_is_unlimited
Unexecuted instantiation: ssl-settings.c:settings_value_is_unlimited
Unexecuted instantiation: settings.c:settings_value_is_unlimited
Unexecuted instantiation: settings-parser.c:settings_value_is_unlimited
334
335
void settings_set_config_binary(enum settings_binary binary);
336
enum settings_binary settings_get_config_binary(void);
337
338
#endif