/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 |