Coverage Report

Created: 2026-08-31 06:47

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