Coverage Report

Created: 2026-09-14 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib-settings/settings.c
Line
Count
Source
1
/* Copyright (c) Dovecot authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "array.h"
5
#include "hash.h"
6
#include "llist.h"
7
#include "str.h"
8
#include "strescape.h"
9
#include "event-filter-private.h"
10
#include "wildcard-match.h"
11
#include "mmap-util.h"
12
#include "dns-util.h"
13
#include "settings.h"
14
#include "var-expand.h"
15
16
#include <ctype.h>
17
#include <sys/stat.h>
18
19
enum set_seen_type {
20
  /* Setting has not been changed */
21
  SET_SEEN_NO,
22
  /* Setting has been changed */
23
  SET_SEEN_YES,
24
  /* Setting has been changed with SETTINGS_OVERRIDE_TYPE_2ND_DEFAULT.
25
     If SETTINGS_OVERRIDE_TYPE_DEFAULT override is still found, use that
26
     instead. */
27
  SET_SEEN_DEFAULT,
28
};
29
30
struct settings_mmap_pool {
31
  struct pool pool;
32
  int refcount;
33
34
  struct settings_mmap_pool *prev, *next;
35
36
  const char *source_filename;
37
  unsigned int source_linenum;
38
39
  pool_t parent_pool;
40
  struct settings_mmap *mmap; /* NULL for unit tests */
41
  struct settings_root *root;
42
};
43
44
struct settings_override {
45
  pool_t pool;
46
  ARRAY_TYPE(settings_override) *overrides_array;
47
  enum settings_override_type type;
48
49
  /* Number of named list filter elements in this override */
50
  unsigned int filter_array_element_count;
51
  /* Number of named (non-list) filter elements in this override */
52
  unsigned int filter_element_count;
53
  /* key += value is used, i.e. append this value to existing value */
54
  bool append;
55
  bool array_default_added;
56
  /* Original key for the overridden setting, e.g.
57
     namespace/inbox/mailbox/Sent/mail_attribute/dict_driver */
58
  const char *orig_key;
59
  /* Final key for the overridden setting, e.g. dict_driver for the above
60
     orig_key example. */
61
  const char *key;
62
  /* Value for the overridden setting */
63
  const char *value;
64
65
  /* Event filter being generated from the key as it's being processed. */
66
  struct event_filter *filter;
67
  /* Last filter element's key, and for list filters the value. For
68
     example:
69
     - namespace/inbox/key: "namespace", "inbox"
70
     - mail_attribute/key: "mail_attribute", NULL
71
  */
72
  const char *last_filter_key, *last_filter_value;
73
74
  /* NULL-terminated list of block names (setting_parser_info names)
75
     which contain this setting key. */
76
  const char *const *block_names;
77
};
78
ARRAY_DEFINE_TYPE(settings_override, struct settings_override);
79
80
struct settings_group {
81
  const char *label;
82
  const char *name;
83
};
84
ARRAY_DEFINE_TYPE(settings_group, struct settings_group);
85
86
struct settings_mmap_block {
87
  const char *name;
88
  size_t block_end_offset;
89
90
  uint32_t filter_count;
91
  const uint64_t *filter_offsets;
92
  const uint32_t *filter_indexes;
93
94
  uint32_t settings_count;
95
  size_t settings_keys_offset;
96
  /* TRUE if settings have been validated against setting_parser_info */
97
  bool settings_validated;
98
};
99
100
struct settings_mmap_event_filter {
101
  struct event_filter *filter;
102
  bool is_group;
103
104
  uint32_t named_list_filter_count;
105
};
106
107
struct settings_mmap {
108
  int refcount;
109
  pool_t pool;
110
  struct settings_root *root;
111
112
  void *mmap_base;
113
  size_t mmap_size;
114
115
  uint32_t all_keys_hash_key_prefix;
116
  uint32_t all_keys_hash_count;
117
  const uint32_t *all_keys_hash;
118
  const unsigned char *all_keys_base;
119
120
  uint32_t block_names_count;
121
  const uint32_t *block_names_rel_offsets;
122
123
  struct settings_mmap_event_filter *event_filters;
124
  unsigned int event_filters_count;
125
126
  HASH_TABLE(const char *, struct settings_mmap_block *) blocks;
127
};
128
129
struct settings_root {
130
  pool_t pool;
131
  const char *protocol_name;
132
  struct settings_mmap *mmap;
133
  ARRAY_TYPE(settings_override) overrides;
134
135
  struct settings_mmap_pool *settings_pools;
136
};
137
138
struct settings_instance {
139
  pool_t pool;
140
  struct settings_root *root;
141
  struct settings_mmap *mmap;
142
  ARRAY_TYPE(settings_override) overrides;
143
};
144
145
struct settings_apply_override {
146
  struct settings_override *set;
147
  unsigned int order;
148
};
149
150
struct settings_apply_ctx {
151
  struct event *event;
152
  struct settings_root *root;
153
  struct settings_instance *instance;
154
  const struct setting_parser_info *info;
155
  enum settings_get_flags flags;
156
  pool_t temp_pool;
157
158
  var_expand_escape_func_t *escape_func;
159
  void *escape_context;
160
161
  const char *filter_key;
162
  const char *filter_value;
163
  const char *filter_name;
164
  bool filter_name_required;
165
  bool seen_filter;
166
167
  struct setting_parser_context *parser;
168
  struct settings_mmap_pool *mpool;
169
  void *set_struct;
170
  ARRAY(enum set_seen_type) set_seen;
171
  ARRAY(struct settings_apply_override) overrides;
172
  ARRAY_TYPE(settings_group) include_groups;
173
174
  string_t *str;
175
  struct var_expand_params var_params;
176
};
177
178
static ARRAY(const struct setting_parser_info *) set_registered_infos;
179
180
static const char *settings_override_type_names[] = {
181
  "default", "userdb", "-o parameter",
182
  "2nd default", "2nd parameter", "hardcoded"
183
};
184
static_assert_array_size(settings_override_type_names,
185
       SETTINGS_OVERRIDE_TYPE_COUNT);
186
187
static struct event_filter event_filter_match_never, event_filter_match_always;
188
0
#define EVENT_FILTER_MATCH_ALWAYS (&event_filter_match_always)
189
0
#define EVENT_FILTER_MATCH_NEVER (&event_filter_match_never)
190
191
static int
192
settings_instance_override(struct settings_apply_ctx *ctx,
193
         struct settings_mmap_event_filter *set_filter,
194
         bool *defaults, const char **error_r);
195
196
static bool settings_local_name_cmp(const char *value, const char *wanted_value)
197
0
{
198
0
  return dns_match_wildcard(value, wanted_value) == 0;
199
0
}
200
201
static void settings_override_free(struct settings_override *override)
202
0
{
203
0
  if (override->filter != EVENT_FILTER_MATCH_ALWAYS &&
204
0
      override->filter != EVENT_FILTER_MATCH_NEVER)
205
0
    event_filter_unref(&override->filter);
206
0
}
207
208
static int
209
settings_block_read_uint64(struct settings_mmap *mmap,
210
         size_t *offset, size_t end_offset,
211
         const char *name, uint64_t *num_r,
212
         const char **error_r)
213
0
{
214
0
  if (*offset + sizeof(*num_r) > end_offset) {
215
0
    *error_r = t_strdup_printf(
216
0
      "Area too small when reading uint of '%s' "
217
0
      "(offset=%zu, end_offset=%zu, file_size=%zu)", name,
218
0
      *offset, end_offset, mmap->mmap_size);
219
0
    return -1;
220
0
  }
221
0
  memcpy(num_r, CONST_PTR_OFFSET(mmap->mmap_base, *offset),
222
0
         sizeof(*num_r));
223
0
  *offset += sizeof(*num_r);
224
0
  return 0;
225
0
}
226
227
static int
228
settings_block_read_uint32(struct settings_mmap *mmap,
229
         size_t *offset, size_t end_offset,
230
         const char *name, uint32_t *num_r,
231
         const char **error_r)
232
0
{
233
0
  if (*offset + sizeof(*num_r) > end_offset) {
234
0
    *error_r = t_strdup_printf(
235
0
      "Area too small when reading uint of '%s' "
236
0
      "(offset=%zu, end_offset=%zu, file_size=%zu)", name,
237
0
      *offset, end_offset, mmap->mmap_size);
238
0
    return -1;
239
0
  }
240
0
  memcpy(num_r, CONST_PTR_OFFSET(mmap->mmap_base, *offset),
241
0
         sizeof(*num_r));
242
0
  *offset += sizeof(*num_r);
243
0
  return 0;
244
0
}
245
246
static int
247
settings_block_read_size(struct settings_mmap *mmap,
248
       size_t *offset, size_t end_offset,
249
       const char *name, uint64_t *size_r,
250
       const char **error_r)
251
0
{
252
0
  if (*offset + sizeof(*size_r) > end_offset) {
253
0
    *error_r = t_strdup_printf(
254
0
      "Area too small when reading size of '%s' "
255
0
      "(offset=%zu, end_offset=%zu, file_size=%zu)", name,
256
0
      *offset, end_offset, mmap->mmap_size);
257
0
    return -1;
258
0
  }
259
0
  memcpy(size_r, CONST_PTR_OFFSET(mmap->mmap_base, *offset),
260
0
         sizeof(*size_r));
261
0
  if (*size_r > end_offset - *offset - sizeof(*size_r)) {
262
0
    *error_r = t_strdup_printf(
263
0
      "'%s' points outside area "
264
0
      "(offset=%zu, size=%"PRIu64", end_offset=%zu, file_size=%zu)",
265
0
      name, *offset, *size_r, end_offset,
266
0
      mmap->mmap_size);
267
0
    return -1;
268
0
  }
269
0
  *offset += sizeof(*size_r);
270
0
  return 0;
271
0
}
272
273
static int
274
settings_block_read_str(struct settings_mmap *mmap,
275
      size_t *offset, size_t end_offset, const char *name,
276
      const char **str_r, const char **error_r)
277
0
{
278
0
  *str_r = (const char *)mmap->mmap_base + *offset;
279
0
  *offset += strlen(*str_r) + 1;
280
0
  if (*offset > end_offset) {
281
0
    *error_r = t_strdup_printf("'%s' points outside area "
282
0
      "(offset=%zu, end_offset=%zu, file_size=%zu)",
283
0
      name, *offset, end_offset, mmap->mmap_size);
284
0
    return -1;
285
0
  }
286
0
  return 0;
287
0
}
288
289
static bool
290
settings_filter_node_match_service(struct event_filter_node *node,
291
           const char *service_name, bool op_not)
292
0
{
293
0
  const char *node_service;
294
295
  /* Not perfect logic, but enough for the settings filters */
296
0
  switch (node->op) {
297
0
  case EVENT_FILTER_OP_CMP_EQ:
298
0
    if (node->type == EVENT_FILTER_NODE_TYPE_EVENT_FIELD_EXACT &&
299
0
        strcmp(node->field.key, SETTINGS_EVENT_FILTER_NAME) == 0 &&
300
0
        node->field.value_type == EVENT_FIELD_VALUE_TYPE_STR &&
301
0
        str_begins(node->field.value.str, "service/", &node_service)) {
302
0
      bool match = strcmp(node_service, service_name) == 0;
303
0
      return match != op_not;
304
0
    }
305
0
    break;
306
0
  case EVENT_FILTER_OP_AND:
307
0
    if (!settings_filter_node_match_service(node->children[0],
308
0
              service_name, op_not) ||
309
0
        !settings_filter_node_match_service(node->children[1],
310
0
              service_name, op_not))
311
0
      return FALSE;
312
0
    break;
313
0
  case EVENT_FILTER_OP_OR:
314
0
    if (!settings_filter_node_match_service(node->children[0],
315
0
              service_name, op_not) &&
316
0
        !settings_filter_node_match_service(node->children[1],
317
0
              service_name, op_not))
318
0
      return FALSE;
319
0
    break;
320
0
  case EVENT_FILTER_OP_NOT:
321
0
    return settings_filter_node_match_service(node->children[0],
322
0
                service_name, !op_not);
323
0
  default:
324
0
    break;
325
0
  }
326
0
  return TRUE;
327
0
}
328
329
static bool
330
settings_filter_match_service(struct event_filter *filter,
331
            const char *service_name)
332
0
{
333
0
  struct event_filter_node *node = event_filter_get_root_node(filter, 0);
334
0
  i_assert(node != NULL);
335
0
  i_assert(event_filter_get_root_node(filter, 1) == NULL);
336
0
  return settings_filter_node_match_service(node, service_name, FALSE);
337
0
}
338
339
static bool
340
settings_event_filter_node_name_find(struct event_filter_node *node,
341
             const char *filter_name, bool op_not)
342
0
{
343
  /* Not perfect logic, but enough for the settings filters */
344
0
  switch (node->op) {
345
0
  case EVENT_FILTER_OP_CMP_EQ:
346
0
    if (!op_not &&
347
0
        node->type == EVENT_FILTER_NODE_TYPE_EVENT_FIELD_EXACT &&
348
0
        strcmp(node->field.key, SETTINGS_EVENT_FILTER_NAME) == 0 &&
349
0
        node->field.value_type == EVENT_FIELD_VALUE_TYPE_STR &&
350
0
        strcmp(node->field.value.str, filter_name) == 0)
351
0
      return TRUE;
352
0
    break;
353
0
  case EVENT_FILTER_OP_AND:
354
0
  case EVENT_FILTER_OP_OR:
355
0
    if (settings_event_filter_node_name_find(node->children[0],
356
0
               filter_name, op_not))
357
0
      return TRUE;
358
0
    if (settings_event_filter_node_name_find(node->children[1],
359
0
               filter_name, op_not))
360
0
      return TRUE;
361
0
    break;
362
0
  case EVENT_FILTER_OP_NOT:
363
0
    return settings_event_filter_node_name_find(node->children[0],
364
0
                  filter_name, !op_not);
365
0
  default:
366
0
    break;
367
0
  }
368
0
  return FALSE;
369
0
}
370
371
static bool
372
settings_event_filter_name_find(struct event_filter *filter,
373
        const char *filter_name)
374
0
{
375
  /* NOTE: The event filter is using EVENT_FIELD_EXACT, so the value has
376
     already removed wildcard escapes. */
377
0
  struct event_filter_node *node = event_filter_get_root_node(filter, 0);
378
0
  i_assert(node != NULL);
379
0
  i_assert(event_filter_get_root_node(filter, 1) == NULL);
380
0
  return settings_event_filter_node_name_find(node, filter_name, FALSE);
381
0
}
382
383
static int
384
settings_read_config_paths(struct settings_mmap *mmap,
385
         enum settings_read_flags flags,
386
         size_t *offset, const char **error_r)
387
0
{
388
0
  uint32_t count;
389
0
  if (settings_block_read_uint32(mmap, offset, mmap->mmap_size,
390
0
               "config paths count", &count,
391
0
               error_r) < 0)
392
0
    return -1;
393
394
0
  for (uint32_t i = 0; i < count; i++) {
395
0
    const char *config_path;
396
0
    if (settings_block_read_str(mmap, offset, mmap->mmap_size,
397
0
              "config path", &config_path,
398
0
              error_r) < 0)
399
0
      return -1;
400
0
    uint64_t inode, size;
401
0
    if (settings_block_read_uint64(mmap, offset, mmap->mmap_size,
402
0
                 "config path inode",
403
0
                 &inode, error_r) < 0)
404
0
      return -1;
405
0
    if (settings_block_read_uint64(mmap, offset, mmap->mmap_size,
406
0
                 "config path size",
407
0
                 &size, error_r) < 0)
408
0
      return -1;
409
0
    uint32_t mtime_sec, mtime_nsec, ctime_sec, ctime_nsec;
410
0
    if (settings_block_read_uint32(mmap, offset, mmap->mmap_size,
411
0
                 "config path mtime sec",
412
0
                 &mtime_sec, error_r) < 0)
413
0
      return -1;
414
0
    if (settings_block_read_uint32(mmap, offset, mmap->mmap_size,
415
0
                 "config path mtime nsec",
416
0
                 &mtime_nsec, error_r) < 0)
417
0
      return -1;
418
419
0
    if (settings_block_read_uint32(mmap, offset, mmap->mmap_size,
420
0
                 "config path ctime sec",
421
0
                 &ctime_sec, error_r) < 0)
422
0
      return -1;
423
0
    if (settings_block_read_uint32(mmap, offset, mmap->mmap_size,
424
0
                 "config path ctime nsec",
425
0
                 &ctime_nsec, error_r) < 0)
426
0
      return -1;
427
428
0
    if ((flags & SETTINGS_READ_CHECK_CACHE_TIMESTAMPS) == 0)
429
0
      continue;
430
431
0
    struct stat st;
432
0
    if (stat(config_path, &st) < 0) {
433
0
      if (errno == ENOENT || ENOACCESS(errno))
434
0
        return 0;
435
0
      *error_r = t_strdup_printf("stat(%s) failed: %m",
436
0
               config_path);
437
0
      return -1;
438
0
    }
439
0
    if (st.st_ino != inode || (uoff_t)st.st_size != size ||
440
0
        st.st_mtime != mtime_sec || ST_MTIME_NSEC(st) != mtime_nsec ||
441
0
        st.st_ctime != ctime_sec || ST_CTIME_NSEC(st) != ctime_nsec)
442
0
      return 0;
443
0
  }
444
0
  return 1;
445
0
}
446
447
static int
448
settings_read_all_keys(struct settings_mmap *mmap,
449
           size_t *offset, const char **error_r)
450
0
{
451
0
  uint32_t size;
452
0
  if (settings_block_read_uint32(mmap, offset, mmap->mmap_size,
453
0
               "all keys size", &size,
454
0
               error_r) < 0)
455
0
    return -1;
456
0
  mmap->all_keys_base = CONST_PTR_OFFSET(mmap->mmap_base, *offset);
457
0
  size_t end_offset = *offset + size;
458
459
0
  if (*offset % sizeof(uint32_t) != 0)
460
0
    *offset += sizeof(uint32_t) - *offset % sizeof(uint32_t);
461
  /* all keys */
462
0
  if (settings_block_read_uint32(mmap, offset, end_offset,
463
0
               "all keys hash key prefix",
464
0
               &mmap->all_keys_hash_key_prefix,
465
0
               error_r) < 0)
466
0
    return -1;
467
0
  if (settings_block_read_uint32(mmap, offset, end_offset,
468
0
               "all keys hash nodes count",
469
0
               &mmap->all_keys_hash_count,
470
0
               error_r) < 0)
471
0
    return -1;
472
0
  mmap->all_keys_hash = CONST_PTR_OFFSET(mmap->mmap_base, *offset);
473
474
  /* block names */
475
0
  *offset += sizeof(uint32_t) * mmap->all_keys_hash_count;
476
0
  if (settings_block_read_uint32(mmap, offset, mmap->mmap_size,
477
0
               "block names count",
478
0
               &mmap->block_names_count,
479
0
               error_r) < 0)
480
0
    return -1;
481
0
  mmap->block_names_rel_offsets =
482
0
    CONST_PTR_OFFSET(mmap->mmap_base, *offset);
483
484
0
  *offset = end_offset;
485
0
  return 0;
486
0
}
487
488
static int
489
settings_read_filters(struct settings_mmap *mmap, const char *service_name,
490
          enum settings_read_flags flags, size_t *offset,
491
          ARRAY_TYPE(const_string) *protocols, const char **error_r)
492
0
{
493
0
  const char *filter_string, *error;
494
495
0
  if (settings_block_read_uint32(mmap, offset, mmap->mmap_size,
496
0
               "filters count",
497
0
               &mmap->event_filters_count,
498
0
               error_r) < 0)
499
0
    return -1;
500
501
0
  mmap->event_filters = mmap->event_filters_count == 0 ? NULL :
502
0
    p_new(mmap->pool, struct settings_mmap_event_filter,
503
0
          mmap->event_filters_count);
504
505
0
  for (uint32_t i = 0; i < mmap->event_filters_count; i++) {
506
0
    struct settings_mmap_event_filter *set_filter =
507
0
      &mmap->event_filters[i];
508
0
    if (settings_block_read_str(mmap, offset, mmap->mmap_size,
509
0
              "filter string", &filter_string,
510
0
              error_r) < 0)
511
0
      return -1;
512
0
    if (settings_block_read_uint32(mmap, offset, mmap->mmap_size,
513
0
          "named list filter element count",
514
0
          &set_filter->named_list_filter_count,
515
0
          error_r) < 0)
516
0
      return -1;
517
518
0
    if (filter_string[0] == '\0') {
519
0
      set_filter->filter = EVENT_FILTER_MATCH_ALWAYS;
520
0
      continue;
521
0
    }
522
523
0
    struct event_filter *tmp_filter = event_filter_create();
524
0
    if (event_filter_parse_case_sensitive(filter_string,
525
0
                  tmp_filter, &error) < 0) {
526
0
      *error_r = t_strdup_printf(
527
0
        "Received invalid filter '%s' at index %u: %s",
528
0
        filter_string, i, error);
529
0
      event_filter_unref(&tmp_filter);
530
0
      return -1;
531
0
    }
532
0
    bool op_not;
533
0
    const char *value =
534
0
      event_filter_find_field_exact(tmp_filter, "protocol", &op_not);
535
0
    if (value != NULL) {
536
0
      if (op_not)
537
0
        value = t_strconcat("!", value, NULL);
538
0
      if (array_lsearch(protocols, &value, i_strcmp_p) == NULL) {
539
0
        value = t_strdup(value);
540
0
        array_push_back(protocols, &value);
541
0
      }
542
543
0
      if (mmap->root->protocol_name != NULL &&
544
0
          (strcmp(mmap->root->protocol_name, value) == 0) == op_not &&
545
0
          (flags & SETTINGS_READ_NO_PROTOCOL_FILTER) == 0) {
546
        /* protocol doesn't match */
547
0
        set_filter->filter = EVENT_FILTER_MATCH_NEVER;
548
0
        event_filter_unref(&tmp_filter);
549
0
        continue;
550
0
      }
551
0
    }
552
0
    if (service_name != NULL &&
553
0
        !settings_filter_match_service(tmp_filter, service_name)) {
554
      /* service name doesn't match */
555
0
      set_filter->filter = EVENT_FILTER_MATCH_NEVER;
556
0
      event_filter_unref(&tmp_filter);
557
0
      continue;
558
0
    }
559
0
    set_filter->is_group =
560
0
      event_filter_has_field_prefix(tmp_filter,
561
0
        SETTINGS_EVENT_FILTER_NAME,
562
0
        SETTINGS_INCLUDE_GROUP_PREFIX_S);
563
564
0
    set_filter->filter = event_filter_create_with_pool(mmap->pool);
565
0
    event_filter_register_cmp(set_filter->filter, "local_name",
566
0
            settings_local_name_cmp);
567
0
    pool_ref(mmap->pool);
568
0
    event_filter_merge(set_filter->filter, tmp_filter,
569
0
           EVENT_FILTER_MERGE_OP_OR);
570
0
    event_filter_unref(&tmp_filter);
571
0
  }
572
0
  return 0;
573
0
}
574
575
static int
576
settings_block_read(struct settings_mmap *mmap, size_t *_offset,
577
        const char **error_r)
578
0
{
579
0
  size_t offset = *_offset;
580
0
  size_t block_size_offset = offset;
581
0
  const char *key, *error;
582
583
  /* <block size> */
584
0
  uint64_t block_size;
585
0
  if (settings_block_read_size(mmap, &offset, mmap->mmap_size,
586
0
             "block size", &block_size, error_r) < 0)
587
0
    return -1;
588
0
  size_t block_end_offset = offset + block_size;
589
590
  /* Verify that block ends with NUL. This way we can safely use strlen()
591
     later on and we know it won't read past the mmaped memory area and
592
     cause a crash. The NUL is either from the last settings value or
593
     from the last error string. */
594
0
  if (((const char *)mmap->mmap_base)[block_end_offset-1] != '\0') {
595
0
    *error_r = t_strdup_printf(
596
0
      "Settings block doesn't end with NUL at offset %zu",
597
0
      block_end_offset-1);
598
0
    return -1;
599
0
  }
600
601
  /* <block name> */
602
0
  const char *block_name;
603
0
  if (settings_block_read_str(mmap, &offset, block_end_offset,
604
0
            "block name", &block_name, error_r) < 0)
605
0
    return -1;
606
607
0
  struct settings_mmap_block *block =
608
0
    hash_table_lookup(mmap->blocks, block_name);
609
0
  if (block != NULL) {
610
0
    *error_r = t_strdup_printf(
611
0
      "Duplicate block name '%s' (offset=%zu)",
612
0
      block_name, block_size_offset);
613
0
    return -1;
614
0
  }
615
0
  block = p_new(mmap->pool, struct settings_mmap_block, 1);
616
0
  block->name = block_name;
617
0
  block->block_end_offset = block_end_offset;
618
0
  hash_table_insert(mmap->blocks, block->name, block);
619
620
  /* <settings count> */
621
0
  if (settings_block_read_uint32(mmap, &offset, block_end_offset,
622
0
               "settings count", &block->settings_count,
623
0
               error_r) < 0)
624
0
    return -1;
625
0
  block->settings_keys_offset = offset;
626
  /* skip over the settings keys for now - they will be validated later */
627
0
  for (uint32_t i = 0; i < block->settings_count; i++) {
628
0
    if (settings_block_read_str(mmap, &offset, block_end_offset,
629
0
              "setting key", &key, error_r) < 0)
630
0
      return -1;
631
0
  }
632
633
  /* <filter count> */
634
0
  if (settings_block_read_uint32(mmap, &offset, block_end_offset,
635
0
               "filter count", &block->filter_count,
636
0
               error_r) < 0)
637
0
    return -1;
638
639
  /* filters */
640
0
  unsigned int filter_idx;
641
0
  for (filter_idx = 0; filter_idx < block->filter_count; filter_idx++) {
642
    /* <filter settings size> */
643
0
    uint64_t filter_settings_size;
644
0
    if (settings_block_read_size(mmap, &offset,
645
0
        block_end_offset, "filter settings size",
646
0
        &filter_settings_size, error_r) < 0)
647
0
      return -1;
648
649
    /* <error string> */
650
0
    size_t tmp_offset = offset;
651
0
    size_t filter_end_offset = offset + filter_settings_size;
652
0
    if (settings_block_read_str(mmap, &tmp_offset,
653
0
              filter_end_offset,
654
0
              "filter error string", &error,
655
0
              error_r) < 0)
656
0
      return -1;
657
658
0
    uint32_t include_count;
659
0
    if (settings_block_read_uint32(mmap, &tmp_offset,
660
0
                 filter_end_offset,
661
0
                 "include group count",
662
0
                 &include_count, error_r) < 0)
663
0
      return -1;
664
665
0
    for (uint32_t i = 0; i < include_count; i++) {
666
      /* <group label> */
667
0
      const char *group_label;
668
0
      if (settings_block_read_str(mmap, &tmp_offset,
669
0
                filter_end_offset,
670
0
                "group label string",
671
0
                &group_label, error_r) < 0)
672
0
        return -1;
673
674
      /* <group name> */
675
0
      const char *group_name;
676
0
      if (settings_block_read_str(mmap, &tmp_offset,
677
0
                filter_end_offset,
678
0
                "group name string",
679
0
                &group_name, error_r) < 0)
680
0
        return -1;
681
0
    }
682
683
    /* skip over the filter contents for now */
684
0
    offset += filter_settings_size;
685
0
  }
686
687
0
  if (offset % sizeof(uint64_t) != 0)
688
0
    offset += sizeof(uint64_t) - offset % sizeof(uint64_t);
689
0
  block->filter_offsets = CONST_PTR_OFFSET(mmap->mmap_base, offset);
690
0
  offset += sizeof(uint64_t) * block->filter_count;
691
0
  block->filter_indexes = CONST_PTR_OFFSET(mmap->mmap_base, offset);
692
0
  offset += sizeof(uint32_t) * block->filter_count;
693
0
  offset++; /* safety NUL */
694
695
0
  if (offset != block_end_offset) {
696
0
    *error_r = t_strdup_printf(
697
0
      "Filter end offset mismatch (%zu != %zu)",
698
0
      offset, block_end_offset);
699
0
    return -1;
700
0
  }
701
0
  *_offset = offset;
702
0
  return 0;
703
0
}
704
705
static int
706
settings_mmap_parse(struct settings_mmap *mmap, const char *service_name,
707
        enum settings_read_flags flags,
708
        const char *const **specific_protocols_r,
709
        const char **error_r)
710
0
{
711
  /*
712
     See ../config/config-dump-full.c for the binary config file format
713
     description.
714
715
     Settings are read until the blob size is reached. There is no
716
     padding/alignment. */
717
0
  const unsigned char *mmap_base = mmap->mmap_base;
718
0
  size_t mmap_size = mmap->mmap_size;
719
0
  ARRAY_TYPE(const_string) protocols;
720
721
0
  t_array_init(&protocols, 8);
722
723
0
  const char *magic_prefix = "DOVECOT-CONFIG\t";
724
0
  const unsigned int magic_prefix_len = strlen(magic_prefix);
725
0
  const unsigned char *eol = memchr(mmap_base, '\n', mmap_size);
726
0
  if (mmap_size < magic_prefix_len ||
727
0
      memcmp(magic_prefix, mmap_base, magic_prefix_len) != 0 ||
728
0
      eol == NULL) {
729
0
    *error_r = "File header doesn't begin with DOVECOT-CONFIG line";
730
0
    return -1;
731
0
  }
732
0
  if (mmap_base[magic_prefix_len] != '1' ||
733
0
      mmap_base[magic_prefix_len+1] != '.') {
734
0
    *error_r = t_strdup_printf(
735
0
      "Unsupported config file version '%s'",
736
0
      t_strdup_until(mmap_base + magic_prefix_len, eol));
737
0
    return -1;
738
0
  }
739
740
  /* <settings full size> */
741
0
  size_t full_size_offset = eol - mmap_base + 1;
742
0
  uint64_t settings_full_size;
743
0
  memcpy(&settings_full_size, mmap_base + full_size_offset,
744
0
         sizeof(settings_full_size));
745
0
  if (full_size_offset + sizeof(settings_full_size) +
746
0
      settings_full_size != mmap_size) {
747
0
    *error_r = t_strdup_printf("Full size mismatch: "
748
0
      "Expected %zu + %zu + %"PRIu64", but file size is %zu",
749
0
      full_size_offset, sizeof(settings_full_size),
750
0
      settings_full_size, mmap_size);
751
0
    return -1;
752
0
  }
753
754
0
  size_t offset = full_size_offset + sizeof(settings_full_size);
755
0
  int ret;
756
0
  if ((ret = settings_read_config_paths(mmap, flags, &offset, error_r)) <= 0)
757
0
    return ret;
758
0
  if (settings_read_all_keys(mmap, &offset, error_r) < 0)
759
0
    return -1;
760
0
  if (settings_read_filters(mmap, service_name, flags, &offset,
761
0
          &protocols, error_r) < 0)
762
0
    return -1;
763
764
0
  do {
765
0
    if (settings_block_read(mmap, &offset, error_r) < 0)
766
0
      return -1;
767
0
  } while (offset < mmap_size);
768
769
0
  if (array_count(&protocols) > 0) {
770
0
    array_append_zero(&protocols);
771
0
    *specific_protocols_r = array_front(&protocols);
772
0
  } else {
773
0
    *specific_protocols_r = NULL;
774
0
  }
775
0
  if ((flags & SETTINGS_READ_CHECK_CACHE_TIMESTAMPS) != 0)
776
0
    return 1;
777
0
  return 0;
778
0
}
779
780
static const char *
781
get_invalid_setting_error(struct settings_apply_ctx *ctx, const char *prefix,
782
        const char *key,
783
        const char *value, const char *orig_value)
784
0
{
785
  /* Config process will preprocess var-expand templates when it sees them
786
     and puts them in front of the actual value, separated by LF.
787
   */
788
0
  if (*orig_value == '\1') {
789
0
    orig_value = strchr(orig_value, '\n');
790
0
    i_assert(orig_value != NULL);
791
0
    orig_value++;
792
0
  }
793
0
  string_t *str = t_str_new(64);
794
0
  str_printfa(str, "%s %s=%s", prefix, key, value);
795
0
  if (strcmp(value, orig_value) != 0)
796
0
    str_printfa(str, " (before expansion: %s)", orig_value);
797
0
  str_printfa(str, ": %s", settings_parser_get_error(ctx->parser));
798
0
  return str_c(str);
799
0
}
800
801
static int
802
settings_var_expand(struct settings_apply_ctx *ctx, unsigned int key_idx,
803
        const char **value, const char **error_r)
804
0
{
805
0
  struct settings_file file = { NULL, NULL };
806
0
  const char *orig_value = *value;
807
0
  bool changed;
808
0
  bool want_expand = FALSE;
809
810
  /* check which one to use */
811
0
  if (*orig_value == '\1') {
812
0
    *value = strchr(orig_value, '\n');
813
0
    if (*value == NULL) {
814
0
      *error_r = "Missing template termination LF";
815
0
      return -1;
816
0
    }
817
0
    want_expand = TRUE;
818
    /* Move past newline */
819
0
    (*value)++;
820
0
  }
821
822
0
  if ((ctx->flags & SETTINGS_GET_FLAG_NO_EXPAND) != 0)
823
0
    return 0;
824
825
0
  if (ctx->info->defines[key_idx].type == SET_STR_NOVARS ||
826
0
      ctx->info->defines[key_idx].type == SET_FILTER_ARRAY)
827
0
    return 0;
828
829
0
  if (!want_expand && ctx->info->defines[key_idx].type == SET_FILE) {
830
0
    settings_file_get(*value, &ctx->mpool->pool, &file);
831
    /* Make sure only the file path is var-expanded. */
832
0
    orig_value = file.path;
833
0
  }
834
835
0
  enum setting_type set_type = ctx->info->defines[key_idx].type;
836
0
  if (set_type == SET_PATH_FILE || set_type == SET_PATH_DIR) {
837
    /* Note: for these types *value points to the raw value both
838
       with and without a config-exported template. */
839
0
    const char *path = *value;
840
0
    size_t path_len = strlen(path);
841
0
    bool path_changed = FALSE;
842
843
0
    if (set_type == SET_PATH_DIR &&
844
0
        path_len > 0 && path[path_len-1] == '/') {
845
      /* drop trailing '/' */
846
0
      path = t_strndup(path, path_len - 1);
847
0
      path_changed = TRUE;
848
0
    }
849
0
    if (str_begins_with(path, "~/") || strcmp(path, "~") == 0) {
850
      /* Convert the ~/ prefix to the %{home} variable and
851
         let it be expanded like the other %variables. */
852
0
      path = t_strconcat("%{home}", path + 1, NULL);
853
0
      path_changed = TRUE;
854
0
    }
855
0
    if (path_changed) {
856
      /* This replaces any config-exported var_expand
857
         template, since the template was compiled from the
858
         original value. */
859
0
      orig_value = path;
860
0
      if (!want_expand && strchr(path, '%') == NULL) {
861
        /* no %variables - only the path changed */
862
0
        *value = p_strdup(&ctx->mpool->pool, path);
863
0
        return 1;
864
0
      }
865
0
      want_expand = TRUE;
866
0
    }
867
0
  }
868
869
  /* Ensure we don't potentially have %{ values that we missed,
870
     and since this will be quite often called, just check for
871
     % and run it through var-expand.
872
873
     Most the misses will come from default settings and overrides
874
     that are not processed by config process.
875
  */
876
0
  if (!want_expand && strchr(orig_value, '%') != NULL)
877
0
    want_expand = TRUE;
878
879
0
  if (!want_expand) {
880
    /* fast path: No %variables in the value */
881
0
    changed = FALSE;
882
0
  } else {
883
0
    struct var_expand_program *program;
884
0
    if (*orig_value == '\1') {
885
0
      i_assert(*value != NULL);
886
      /* import after \1 to terminating newline, exclusive */
887
0
      if (var_expand_program_import_sized(orig_value + 1,
888
0
                *value - orig_value - 2,
889
0
                &program, error_r) < 0)
890
0
        return -1;
891
0
    } else if (var_expand_program_create(orig_value, &program,
892
0
                 error_r) < 0) {
893
0
      return -1;
894
0
    }
895
896
0
    str_truncate(ctx->str, 0);
897
0
    int ret = var_expand_program_execute(ctx->str, program,
898
0
                 &ctx->var_params, error_r);
899
0
    var_expand_program_free(&program);
900
0
    if (ret < 0 && (ctx->flags & SETTINGS_GET_FLAG_FAKE_EXPAND) == 0)
901
0
      return -1;
902
0
    changed = strcmp(*value, str_c(ctx->str)) != 0;
903
0
  }
904
905
0
  if (!changed) {
906
0
    return 0;
907
0
  } else if (ctx->info->defines[key_idx].type == SET_FILE) {
908
0
    file.path = str_c(ctx->str);
909
0
    if (settings_parse_read_file(file.path, file.path,
910
0
               &ctx->mpool->pool, NULL,
911
0
               "", value, error_r) < 0)
912
0
      return -1;
913
0
  } else {
914
0
    *value = p_strdup(&ctx->mpool->pool, str_c(ctx->str));
915
0
  }
916
0
  return 1;
917
0
}
918
919
static int
920
settings_mmap_apply_key(struct settings_apply_ctx *ctx, unsigned int key_idx,
921
      const char *list_key, const char *value,
922
      const char **error_r)
923
0
{
924
0
  const char *key = ctx->info->defines[key_idx].key;
925
0
  const char *error, *orig_value = value;
926
0
  if (list_key != NULL)
927
0
    key = t_strdup_printf("%s/%s", key, list_key);
928
929
  /* call settings_apply() before variable expansion */
930
0
  enum setting_apply_flags apply_flags =
931
0
    (ctx->flags & SETTINGS_GET_FLAG_NO_EXPAND) == 0 ? 0 :
932
0
    SETTING_APPLY_FLAG_NO_EXPAND;
933
934
0
  const char *orig_ptr = value;
935
936
0
  if (*value == '\1') {
937
0
    value = strchr(value, '\n');
938
0
    if (value == NULL) {
939
0
      *error_r = "Missing template termination LF";
940
0
      return -1;
941
0
    }
942
0
    value++;
943
0
    orig_ptr = value;
944
0
  }
945
946
  /* Provide the non-exported template here */
947
0
  if (ctx->info->setting_apply != NULL &&
948
0
      !ctx->info->setting_apply(ctx->event, ctx->set_struct, key, &value,
949
0
              apply_flags, error_r)) {
950
0
    *error_r = t_strdup_printf("Invalid setting %s=%s: %s",
951
0
             key, orig_value, *error_r);
952
0
    return -1;
953
0
  }
954
955
  /* If the value didn't change, provide the actual original value
956
     here to make sure settings_var_expand() can import the exported
957
     var_expand template. */
958
0
  if (value == orig_ptr)
959
0
    value = orig_value;
960
961
0
  if (settings_var_expand(ctx, key_idx, &value, &error) < 0) {
962
0
    *error_r = t_strdup_printf(
963
0
      "Failed to expand %s setting variables: %s",
964
0
      key, error);
965
0
    return -1;
966
0
  }
967
  /* value points to mmap()ed memory, which is kept
968
     referenced by the set_pool for the life time of the
969
     settings struct. */
970
0
  if (settings_parse_keyidx_value_nodup(ctx->parser, key_idx,
971
0
                key, value) < 0) {
972
0
    *error_r = get_invalid_setting_error(ctx, "Invalid setting",
973
0
                 key, value, orig_value);
974
0
    return -1;
975
0
  }
976
0
  return 0;
977
0
}
978
979
static int
980
settings_mmap_apply_defaults(struct settings_apply_ctx *ctx,
981
           const char **error_r)
982
0
{
983
0
  enum setting_apply_flags apply_flags = SETTING_APPLY_FLAG_OVERRIDE |
984
0
    ((ctx->flags & SETTINGS_GET_FLAG_NO_EXPAND) == 0 ? 0 :
985
0
     SETTING_APPLY_FLAG_NO_EXPAND);
986
0
  const char *error;
987
0
  unsigned int key_idx;
988
989
0
  for (key_idx = 0; ctx->info->defines[key_idx].key != NULL; key_idx++) {
990
0
    enum set_seen_type *set_seenp =
991
0
      array_idx_get_space(&ctx->set_seen, key_idx);
992
0
    if (*set_seenp == SET_SEEN_YES)
993
0
      continue;
994
995
0
    void *set = PTR_OFFSET(ctx->info->defaults,
996
0
               ctx->info->defines[key_idx].offset);
997
0
    if (!setting_type_is_str_vars(ctx->info->defines[key_idx].type))
998
0
      continue; /* not needed for now */
999
0
    const char *key = ctx->info->defines[key_idx].key;
1000
0
    const char *const *valuep = set;
1001
0
    const char *value = *valuep;
1002
0
    if (value == NULL)
1003
0
      continue;
1004
1005
0
    if (ctx->info->setting_apply != NULL &&
1006
0
        !ctx->info->setting_apply(ctx->event, ctx->set_struct, key,
1007
0
                &value, apply_flags, &error))
1008
0
      i_panic("BUG: Failed to apply default setting %s=%s: %s",
1009
0
        key, value, error);
1010
1011
0
    int ret = settings_var_expand(ctx, key_idx, &value, &error);
1012
0
    if (ret < 0) {
1013
0
      *error_r = t_strdup_printf(
1014
0
        "Failed to expand default setting %s=%s variables: %s",
1015
0
        key, value, error);
1016
0
      return -1;
1017
0
    }
1018
0
    if (ret > 0 &&
1019
0
        settings_parse_keyidx_value(ctx->parser, key_idx,
1020
0
            key, value) < 0) {
1021
0
      *error_r = get_invalid_setting_error(ctx,
1022
0
          "Invalid default setting",
1023
0
          key, value, value);
1024
0
      return -1;
1025
0
    }
1026
0
  }
1027
0
  return 0;
1028
0
}
1029
1030
static int
1031
settings_mmap_apply_blob(struct settings_apply_ctx *ctx,
1032
       struct settings_mmap_block *block,
1033
       size_t start_offset, size_t end_offset,
1034
       const char **error_r)
1035
0
{
1036
0
  struct settings_mmap *mmap = ctx->instance->mmap;
1037
0
  size_t offset = start_offset;
1038
1039
  /* list of settings: key, value, ... */
1040
0
  while (offset < end_offset) {
1041
    /* We already checked that settings blob ends with NUL, so
1042
       strlen() can be used safely. */
1043
0
    uint32_t key_idx;
1044
0
    memcpy(&key_idx, CONST_PTR_OFFSET(mmap->mmap_base, offset),
1045
0
           sizeof(key_idx));
1046
0
    if (key_idx >= block->settings_count) {
1047
0
      *error_r = t_strdup_printf(
1048
0
        "Settings key index too high (%u >= %u)",
1049
0
        key_idx, block->settings_count);
1050
0
      return -1;
1051
0
    }
1052
0
    offset += sizeof(key_idx);
1053
1054
0
    bool set_apply = TRUE;
1055
0
    const char *list_key = NULL;
1056
1057
0
    enum set_seen_type *set_seenp =
1058
0
      array_idx_get_space(&ctx->set_seen, key_idx);
1059
0
    if (*set_seenp != SET_SEEN_NO) {
1060
      /* Already seen this setting - don't set it again.
1061
         This check is used also with boollists when the
1062
         whole list is replaced. */
1063
0
      set_apply = FALSE;
1064
0
    }
1065
0
    bool list_stop = FALSE, list_clear = FALSE;
1066
0
    if (ctx->info->defines[key_idx].type == SET_BOOLLIST ||
1067
0
        ctx->info->defines[key_idx].type == SET_STRLIST) {
1068
0
      const char *type =
1069
0
        (const char *)mmap->mmap_base + offset;
1070
0
      if (type[0] == SET_LIST_REPLACE[0])
1071
0
        list_stop = TRUE;
1072
0
      else if (type[0] == SET_LIST_CLEAR[0]) {
1073
0
        list_stop = TRUE;
1074
0
        list_clear = TRUE;
1075
0
      } else if (type[0] != SET_LIST_APPEND[0]) {
1076
0
        *error_r = t_strdup_printf(
1077
0
          "List type is invalid (offset=%zu)",
1078
0
          offset);
1079
0
        return -1;
1080
0
      }
1081
0
      offset++;
1082
0
    }
1083
1084
0
    if (ctx->info->defines[key_idx].type == SET_STRLIST ||
1085
0
        ctx->info->defines[key_idx].type == SET_BOOLLIST) {
1086
0
      list_key = (const char *)mmap->mmap_base + offset;
1087
0
      offset += strlen(list_key)+1;
1088
      /* Keys from the config are trusted, so expand their
1089
         %variables the same way the values are expanded. This
1090
         is done before the has_key() check so deduplication
1091
         operates on the final key. */
1092
0
      const char *error;
1093
0
      if (settings_var_expand(ctx, key_idx, &list_key,
1094
0
            &error) < 0) {
1095
0
        *error_r = t_strdup_printf(
1096
0
          "Failed to expand %s list key variables: %s",
1097
0
          ctx->info->defines[key_idx].key, error);
1098
0
        return -1;
1099
0
      }
1100
0
      set_apply = set_apply &&
1101
0
        !settings_parse_list_has_key(ctx->parser,
1102
0
          key_idx, settings_section_unescape(list_key));
1103
0
    } else if (ctx->info->defines[key_idx].type == SET_FILTER_ARRAY)
1104
0
      set_apply = TRUE;
1105
0
    else if (set_apply)
1106
0
      *set_seenp = SET_SEEN_YES;
1107
1108
0
    if (offset >= end_offset) {
1109
      /* if offset==end_offset, the value is missing. */
1110
0
      *error_r = t_strdup_printf(
1111
0
        "Settings key/value points outside blob "
1112
0
        "(offset=%zu, end_offset=%zu, file_size=%zu)",
1113
0
        offset, end_offset, mmap->mmap_size);
1114
0
      return -1;
1115
0
    }
1116
0
    const char *value = (const char *)mmap->mmap_base + offset;
1117
0
    offset += strlen(value)+1;
1118
0
    if (offset > end_offset) {
1119
0
      *error_r = t_strdup_printf(
1120
0
        "Settings value points outside blob "
1121
0
        "(offset=%zu, end_offset=%zu, file_size=%zu)",
1122
0
        offset, end_offset, mmap->mmap_size);
1123
0
      return -1;
1124
0
    }
1125
0
    int ret = 0;
1126
0
    T_BEGIN {
1127
0
      if (set_apply && !list_clear) {
1128
0
        ret = settings_mmap_apply_key(ctx, key_idx,
1129
0
          list_key, value, error_r);
1130
0
      }
1131
0
      if (list_stop) {
1132
        /* The lists are filled in reverse order.
1133
           Mark it now as "stopped", so the following
1134
           list settings won't modify it. */
1135
0
        settings_parse_array_stop(ctx->parser, key_idx);
1136
0
      }
1137
0
    } T_END_PASS_STR_IF(ret < 0, error_r);
1138
0
    if (ret < 0)
1139
0
      return -1;
1140
0
  }
1141
0
  return 0;
1142
0
}
1143
1144
static int settings_mmap_validate(struct settings_mmap *mmap,
1145
          struct settings_mmap_block *block,
1146
          const struct setting_parser_info *info,
1147
          const char **error_r)
1148
0
{
1149
0
  size_t offset = block->settings_keys_offset;
1150
0
  const char *key;
1151
0
  uint32_t i;
1152
1153
0
  for (i = 0; info->defines[i].key != NULL; i++) {
1154
0
    if (i >= block->settings_count)
1155
0
      break;
1156
0
    if (settings_block_read_str(mmap, &offset,
1157
0
              block->block_end_offset,
1158
0
              "setting key", &key, error_r) < 0) {
1159
      /* shouldn't happen - we already read it once */
1160
0
      return -1;
1161
0
    }
1162
0
    if (strcmp(info->defines[i].key, key) != 0) {
1163
0
      *error_r = t_strdup_printf(
1164
0
        "settings struct %s #%u key mismatch %s != %s",
1165
0
        info->name, i, info->defines[i].key, key);
1166
0
      return -1;
1167
0
    }
1168
0
  }
1169
0
  if (i != block->settings_count) {
1170
0
    *error_r = t_strdup_printf(
1171
0
      "settings struct %s count mismatch %u != %u",
1172
0
      info->name, i+1, block->settings_count);
1173
0
    return -1;
1174
0
  }
1175
0
  return 0;
1176
0
}
1177
1178
static int
1179
settings_mmap_get_filter_idx(struct settings_mmap *mmap,
1180
           struct settings_mmap_block *block,
1181
           uint32_t filter_idx, uint32_t *event_filter_idx_r,
1182
           const char **error_r)
1183
0
{
1184
0
  *event_filter_idx_r = block->filter_indexes[filter_idx];
1185
0
  if (*event_filter_idx_r >= mmap->event_filters_count) {
1186
0
    *error_r = t_strdup_printf("event filter idx %u >= %u",
1187
0
      *event_filter_idx_r, mmap->event_filters_count);
1188
0
    return -1;
1189
0
  }
1190
0
  return 0;
1191
0
}
1192
1193
static int
1194
settings_mmap_apply_filter(struct settings_apply_ctx *ctx,
1195
         struct settings_mmap_block *block,
1196
         uint32_t filter_idx,
1197
         struct settings_mmap_event_filter *set_filter,
1198
         const char **error_r)
1199
0
{
1200
0
  struct settings_mmap *mmap = ctx->instance->mmap;
1201
0
  uint64_t filter_offset, filter_set_size;
1202
1203
0
  filter_offset = block->filter_offsets[filter_idx];
1204
0
  memcpy(&filter_set_size,
1205
0
         CONST_PTR_OFFSET(mmap->mmap_base, filter_offset),
1206
0
         sizeof(filter_set_size));
1207
0
  filter_offset += sizeof(filter_set_size);
1208
0
  uint64_t filter_end_offset = filter_offset + filter_set_size;
1209
1210
0
  const char *filter_error =
1211
0
    CONST_PTR_OFFSET(mmap->mmap_base, filter_offset);
1212
0
  if (filter_error[0] != '\0') {
1213
0
    *error_r = filter_error;
1214
0
    return -1;
1215
0
  }
1216
0
  filter_offset += strlen(filter_error) + 1;
1217
1218
0
  uint32_t include_count;
1219
0
  memcpy(&include_count, CONST_PTR_OFFSET(mmap->mmap_base, filter_offset),
1220
0
         sizeof(include_count));
1221
0
  filter_offset += sizeof(include_count);
1222
1223
0
  if (ctx->filter_name != NULL && !ctx->seen_filter &&
1224
0
      set_filter->filter != EVENT_FILTER_MATCH_ALWAYS &&
1225
0
      settings_event_filter_name_find(set_filter->filter, ctx->filter_name))
1226
0
    ctx->seen_filter = TRUE;
1227
1228
0
  array_clear(&ctx->include_groups);
1229
0
  for (uint32_t j = 0; j < include_count; j++) {
1230
0
    struct settings_group *include_group =
1231
0
      array_append_space(&ctx->include_groups);
1232
0
    include_group->label =
1233
0
      CONST_PTR_OFFSET(mmap->mmap_base, filter_offset);
1234
0
    filter_offset += strlen(include_group->label) + 1;
1235
1236
0
    include_group->name =
1237
0
      CONST_PTR_OFFSET(mmap->mmap_base, filter_offset);
1238
0
    filter_offset += strlen(include_group->name) + 1;
1239
0
  }
1240
  /* Apply overrides specific to this filter before the
1241
     filter settings themselves. For base settings the
1242
     filter is EVENT_FILTER_MATCH_ALWAYS, which applies
1243
     the rest of the overrides that weren't already
1244
     handled. This way global setting overrides don't
1245
     override named filters' settings, unless the
1246
     override is specifically using the filter name
1247
     as prefix. */
1248
0
  bool defaults = FALSE;
1249
0
  int ret = settings_instance_override(ctx, set_filter,
1250
0
               &defaults, error_r);
1251
0
  if (ret < 0)
1252
0
    return -1;
1253
1254
0
  if (ret > 0)
1255
0
    ctx->seen_filter = TRUE;
1256
1257
0
  if (settings_mmap_apply_blob(ctx, block,
1258
0
             filter_offset, filter_end_offset,
1259
0
             error_r) < 0)
1260
0
    return -1;
1261
0
  if (defaults) {
1262
0
    ret = settings_instance_override(ctx, set_filter,
1263
0
             &defaults, error_r);
1264
0
    if (ret < 0)
1265
0
      return -1;
1266
0
    if (ret > 0)
1267
0
      ctx->seen_filter = TRUE;
1268
0
  }
1269
0
  return 0;
1270
0
}
1271
1272
static struct event *settings_group_event_create(struct settings_apply_ctx *ctx)
1273
0
{
1274
0
  struct event *event = event_create(ctx->event);
1275
0
  const struct settings_group *include_group;
1276
0
  array_foreach(&ctx->include_groups, include_group) {
1277
    /* Add @<group label>/<group name> to matching filters and
1278
       restart the filter processing. */
1279
0
    const char *filter_value = t_strdup_printf(
1280
0
      SETTINGS_INCLUDE_GROUP_PREFIX_S"%s/%s",
1281
0
      include_group->label, include_group->name);
1282
0
    event_strlist_append(event, SETTINGS_EVENT_FILTER_NAME,
1283
0
             filter_value);
1284
0
  }
1285
0
  return event;
1286
0
}
1287
1288
static int
1289
settings_apply_groups(struct settings_apply_ctx *ctx,
1290
          struct settings_mmap *mmap,
1291
          struct settings_mmap_block *block,
1292
          uint32_t include_filter_idx, const char **error_r)
1293
0
{
1294
0
  struct event *event = NULL;
1295
0
  const struct failure_context failure_ctx = {
1296
0
    .type = LOG_TYPE_DEBUG,
1297
0
  };
1298
1299
0
  if (array_is_empty(&ctx->include_groups))
1300
0
    return 0;
1301
1302
  /* All group filters are at the end. When we see a non-group filter,
1303
     we can stop. */
1304
0
  int ret = 0;
1305
0
  for (uint32_t i = block->filter_count; i > 0; ) {
1306
0
    i--;
1307
0
    uint32_t event_filter_idx;
1308
0
    if (settings_mmap_get_filter_idx(mmap, block, i,
1309
0
             &event_filter_idx, error_r) < 0) {
1310
0
      ret = -1;
1311
0
      break;
1312
0
    }
1313
1314
0
    if (!mmap->event_filters[event_filter_idx].is_group)
1315
0
      break;
1316
1317
0
    i_assert(i > include_filter_idx);
1318
0
    struct settings_mmap_event_filter *set_filter =
1319
0
      &mmap->event_filters[event_filter_idx];
1320
0
    i_assert(set_filter->filter != EVENT_FILTER_MATCH_ALWAYS);
1321
0
    if (set_filter->filter == EVENT_FILTER_MATCH_NEVER)
1322
0
      continue;
1323
1324
0
    if (event == NULL) T_BEGIN {
1325
0
      event = settings_group_event_create(ctx);
1326
0
    } T_END;
1327
0
    if (event_filter_match(set_filter->filter, event, &failure_ctx)) {
1328
0
      if (settings_mmap_apply_filter(ctx, block, i,
1329
0
                   set_filter,
1330
0
                   error_r) < 0) {
1331
0
        ret = -1;
1332
0
        break;
1333
0
      }
1334
0
    }
1335
0
  }
1336
1337
0
  event_unref(&event);
1338
0
  return ret;
1339
0
}
1340
1341
static int
1342
settings_mmap_apply(struct settings_apply_ctx *ctx, const char **error_r)
1343
0
{
1344
0
  struct settings_mmap *mmap = ctx->instance->mmap;
1345
0
  struct settings_mmap_block *block =
1346
0
    hash_table_lookup(mmap->blocks, ctx->info->name);
1347
0
  if (block == NULL) {
1348
0
    *error_r = t_strdup_printf(
1349
0
      "BUG: Configuration has no settings struct named '%s'",
1350
0
      ctx->info->name);
1351
0
    return -1;
1352
0
  }
1353
1354
0
  if (!block->settings_validated &&
1355
0
      (ctx->flags & SETTINGS_GET_NO_KEY_VALIDATION) == 0) {
1356
0
    if (settings_mmap_validate(mmap, block, ctx->info, error_r) < 0)
1357
0
      return -1;
1358
0
    block->settings_validated = TRUE;
1359
0
  }
1360
1361
0
  const struct failure_context failure_ctx = {
1362
0
    .type = LOG_TYPE_DEBUG,
1363
0
  };
1364
1365
  /* Go through the filters in reverse sorted order, so we always set the
1366
     setting just once, never overriding anything. A filter for the base
1367
     settings is expected to always exist. */
1368
0
  struct event *event = ctx->event;
1369
0
  for (uint32_t i = block->filter_count; i > 0; ) {
1370
0
    i--;
1371
0
    uint32_t event_filter_idx;
1372
0
    if (settings_mmap_get_filter_idx(mmap, block, i,
1373
0
             &event_filter_idx, error_r) < 0)
1374
0
      return -1;
1375
0
    struct settings_mmap_event_filter *set_filter =
1376
0
      &mmap->event_filters[event_filter_idx];
1377
0
    if (set_filter->filter == EVENT_FILTER_MATCH_NEVER)
1378
0
      ;
1379
0
    else if (set_filter->filter == EVENT_FILTER_MATCH_ALWAYS ||
1380
0
       event_filter_match(set_filter->filter, event, &failure_ctx)) {
1381
0
      i_assert(!set_filter->is_group);
1382
0
      if (settings_mmap_apply_filter(ctx, block, i,
1383
0
                   set_filter, error_r) < 0)
1384
0
        return -1;
1385
1386
      /* Apply all group includes */
1387
0
      if (settings_apply_groups(ctx, mmap, block,
1388
0
              i, error_r) < 0)
1389
0
        return -1;
1390
0
    }
1391
0
  }
1392
0
  return ctx->seen_filter ? 1 : 0;
1393
1394
0
}
1395
1396
static void settings_mmap_ref(struct settings_mmap *mmap)
1397
0
{
1398
0
  i_assert(mmap->refcount > 0);
1399
1400
0
  mmap->refcount++;
1401
0
}
1402
1403
static void settings_mmap_unref(struct settings_mmap **_mmap)
1404
0
{
1405
0
  struct settings_mmap *mmap = *_mmap;
1406
0
  if (mmap == NULL)
1407
0
    return;
1408
0
  i_assert(mmap->refcount > 0);
1409
1410
0
  *_mmap = NULL;
1411
0
  if (--mmap->refcount > 0)
1412
0
    return;
1413
1414
0
  for (unsigned int i = 0; i < mmap->event_filters_count; i++) {
1415
0
    if (mmap->event_filters[i].filter != EVENT_FILTER_MATCH_ALWAYS &&
1416
0
        mmap->event_filters[i].filter != EVENT_FILTER_MATCH_NEVER)
1417
0
      event_filter_unref(&mmap->event_filters[i].filter);
1418
0
  }
1419
0
  hash_table_destroy(&mmap->blocks);
1420
1421
0
  if (munmap(mmap->mmap_base, mmap->mmap_size) < 0)
1422
0
    i_error("munmap(<config>) failed: %m");
1423
0
  pool_unref(&mmap->pool);
1424
0
}
1425
1426
int settings_read(struct settings_root *root, int fd, const char *path,
1427
      const char *service_name, const char *protocol_name,
1428
      enum settings_read_flags flags,
1429
      const char *const **specific_protocols_r,
1430
      const char **error_r)
1431
0
{
1432
0
  pool_t pool = pool_alloconly_create("settings mmap", 1024*16);
1433
0
  struct settings_mmap *mmap = p_new(pool, struct settings_mmap, 1);
1434
0
  mmap->refcount = 1;
1435
0
  mmap->pool = pool;
1436
0
  mmap->mmap_base = mmap_ro_file(fd, &mmap->mmap_size);
1437
0
  if (mmap->mmap_base == MAP_FAILED)
1438
0
    i_fatal("Failed to read config: mmap(%s) failed: %m", path);
1439
0
  if (mmap->mmap_size == 0)
1440
0
    i_fatal("Failed to read config: %s file size is empty", path);
1441
  /* Remember the protocol for following settings lookups */
1442
0
  root->protocol_name = p_strdup(root->pool, protocol_name);
1443
1444
0
  settings_mmap_unref(&root->mmap);
1445
0
  mmap->root = root;
1446
0
  root->mmap = mmap;
1447
0
  hash_table_create(&mmap->blocks, mmap->pool, 0, str_hash, strcmp);
1448
1449
0
  int ret = settings_mmap_parse(root->mmap, service_name, flags,
1450
0
              specific_protocols_r, error_r);
1451
0
  if (ret < 0 ||
1452
0
      (ret == 0 && (flags & SETTINGS_READ_CHECK_CACHE_TIMESTAMPS) != 0))
1453
0
    settings_mmap_unref(&root->mmap);
1454
0
  return ret;
1455
0
}
1456
1457
bool settings_has_mmap(struct settings_root *root)
1458
0
{
1459
0
  return root->mmap != NULL;
1460
0
}
1461
1462
static const char *settings_mmap_pool_get_name(pool_t pool)
1463
0
{
1464
0
  struct settings_mmap_pool *mpool =
1465
0
    container_of(pool, struct settings_mmap_pool, pool);
1466
1467
0
  return pool_get_name(mpool->parent_pool);
1468
0
}
1469
1470
static void settings_mmap_pool_ref(pool_t pool)
1471
0
{
1472
0
  struct settings_mmap_pool *mpool =
1473
0
    container_of(pool, struct settings_mmap_pool, pool);
1474
1475
0
  i_assert(mpool->refcount > 0);
1476
0
  mpool->refcount++;
1477
0
}
1478
1479
static void settings_mmap_pool_unref(pool_t *pool)
1480
0
{
1481
0
  struct settings_mmap_pool *mpool =
1482
0
    container_of(*pool, struct settings_mmap_pool, pool);
1483
1484
0
  i_assert(mpool->refcount > 0);
1485
0
  *pool = NULL;
1486
0
  if (--mpool->refcount > 0)
1487
0
    return;
1488
1489
0
  DLLIST_REMOVE(&mpool->root->settings_pools, mpool);
1490
1491
0
  settings_mmap_unref(&mpool->mmap);
1492
0
  pool_external_refs_unref(&mpool->pool);
1493
0
  pool_unref(&mpool->parent_pool);
1494
0
}
1495
1496
static void *settings_mmap_pool_malloc(pool_t pool, size_t size)
1497
0
{
1498
0
  struct settings_mmap_pool *mpool =
1499
0
    container_of(pool, struct settings_mmap_pool, pool);
1500
1501
0
  return p_malloc(mpool->parent_pool, size);
1502
0
}
1503
1504
static void settings_mmap_pool_free(pool_t pool, void *mem)
1505
0
{
1506
0
  struct settings_mmap_pool *mpool =
1507
0
    container_of(pool, struct settings_mmap_pool, pool);
1508
1509
0
  p_free(mpool->parent_pool, mem);
1510
0
}
1511
1512
static void *settings_mmap_pool_realloc(pool_t pool, void *mem,
1513
          size_t old_size, size_t new_size)
1514
0
{
1515
0
  struct settings_mmap_pool *mpool =
1516
0
    container_of(pool, struct settings_mmap_pool, pool);
1517
1518
0
  return p_realloc(mpool->parent_pool, mem, old_size, new_size);
1519
0
}
1520
1521
static void settings_mmap_pool_clear(pool_t pool ATTR_UNUSED)
1522
0
{
1523
0
  i_panic("settings_mmap_pool_clear() must not be called");
1524
0
}
1525
1526
static size_t settings_mmap_pool_get_max_easy_alloc_size(pool_t pool)
1527
0
{
1528
0
  struct settings_mmap_pool *mpool =
1529
0
    container_of(pool, struct settings_mmap_pool, pool);
1530
1531
0
  return p_get_max_easy_alloc_size(mpool->parent_pool);
1532
0
}
1533
1534
static struct pool_vfuncs static_settings_mmap_pool_vfuncs = {
1535
  settings_mmap_pool_get_name,
1536
1537
  settings_mmap_pool_ref,
1538
  settings_mmap_pool_unref,
1539
1540
  settings_mmap_pool_malloc,
1541
  settings_mmap_pool_free,
1542
1543
  settings_mmap_pool_realloc,
1544
1545
  settings_mmap_pool_clear,
1546
  settings_mmap_pool_get_max_easy_alloc_size
1547
};
1548
1549
static struct settings_mmap_pool *
1550
settings_mmap_pool_create(struct settings_root *root,
1551
        struct settings_mmap *mmap,
1552
        const char *source_filename,
1553
        unsigned int source_linenum)
1554
0
{
1555
0
  struct settings_mmap_pool *mpool;
1556
0
  pool_t parent_pool =
1557
0
    pool_alloconly_create("settings mmap pool", 256);
1558
1559
0
  mpool = p_new(parent_pool, struct settings_mmap_pool, 1);
1560
0
  mpool->pool.v = &static_settings_mmap_pool_vfuncs;
1561
0
  mpool->pool.alloconly_pool = TRUE;
1562
0
  mpool->refcount = 1;
1563
0
  mpool->parent_pool = parent_pool;
1564
0
  mpool->root = root;
1565
0
  mpool->mmap = mmap;
1566
0
  mpool->source_filename = source_filename;
1567
0
  mpool->source_linenum = source_linenum;
1568
0
  if (mmap != NULL)
1569
0
    settings_mmap_ref(mmap);
1570
1571
0
  DLLIST_PREPEND(&root->settings_pools, mpool);
1572
0
  return mpool;
1573
0
}
1574
1575
struct settings_var_expand_init_ctx {
1576
  ARRAY(const struct var_expand_table *) tables;
1577
  ARRAY(const struct var_expand_provider *) providers;
1578
  ARRAY(void *) contexts;
1579
1580
  var_expand_escape_func_t *escape_func;
1581
  void *escape_context;
1582
};
1583
1584
static void
1585
settings_var_expand_init_add(struct settings_var_expand_init_ctx *init_ctx,
1586
           const struct var_expand_params *params)
1587
0
{
1588
0
  unsigned int need_contexts = 1;
1589
0
  static const struct var_expand_table empty_table[] = {
1590
0
    VAR_EXPAND_TABLE_END
1591
0
  };
1592
0
  static const struct var_expand_table *empty_table_ptr = empty_table;
1593
0
  static const struct var_expand_provider empty_provider[] = {
1594
0
    VAR_EXPAND_TABLE_END
1595
0
  };
1596
0
  static const struct var_expand_provider *empty_provider_ptr = empty_provider;
1597
1598
0
  if (params->table != NULL) {
1599
0
    i_assert(params->tables_arr == NULL);
1600
0
    array_push_back(&init_ctx->tables, &params->table);
1601
0
  } else if (params->tables_arr == NULL && params->providers_arr == NULL) {
1602
0
    array_push_back(&init_ctx->tables, &empty_table_ptr);
1603
0
  }
1604
0
  if (params->providers != NULL) {
1605
0
    i_assert(params->providers_arr == NULL);
1606
0
    array_push_back(&init_ctx->providers, &params->providers);
1607
0
  } else if (params->tables_arr == NULL && params->providers_arr == NULL) {
1608
0
    array_push_back(&init_ctx->providers, &empty_provider_ptr);
1609
0
  }
1610
0
  if (params->table != NULL || params->providers != NULL)
1611
0
    array_push_back(&init_ctx->contexts, &params->context);
1612
1613
0
  if (params->tables_arr != NULL || params->providers_arr != NULL) {
1614
0
    unsigned int table_count = 0, prov_count = 0;
1615
0
    const struct var_expand_table *tbl;
1616
0
    const struct var_expand_provider *prov;
1617
1618
    /* Ensure that we get a table and provider so that contexts line up */
1619
0
    do {
1620
0
      tbl = params->tables_arr != NULL ?
1621
0
        params->tables_arr[table_count] : NULL;
1622
0
      prov = params->providers_arr != NULL ?
1623
0
        params->providers_arr[prov_count] : NULL;
1624
1625
      /* for each provider and table, there needs to be
1626
         a correspoding entry in both arrays to make sure
1627
         that when we go through them, we get the correct
1628
         context too.
1629
      */
1630
0
      if (tbl != NULL) {
1631
0
        array_push_back(&init_ctx->tables, &tbl);
1632
0
        table_count++;
1633
0
      } else if (prov != NULL) {
1634
0
        array_push_back(&init_ctx->tables, &empty_table_ptr);
1635
0
      }
1636
0
      if (prov != NULL) {
1637
0
        array_push_back(&init_ctx->providers, &prov);
1638
0
        prov_count++;
1639
0
      } else if (tbl != NULL) {
1640
0
        array_push_back(&init_ctx->providers, &empty_provider_ptr);
1641
0
      }
1642
0
      if (prov == NULL && tbl == NULL)
1643
0
        break;
1644
0
    } while (tbl != NULL || prov != NULL);
1645
1646
0
    if (I_MAX(table_count, prov_count) > need_contexts)
1647
0
      need_contexts = I_MAX(table_count, prov_count);
1648
0
  }
1649
1650
0
  if (params->escape_func != NULL)
1651
0
    init_ctx->escape_func = params->escape_func;
1652
0
  if (params->escape_context != NULL)
1653
0
    init_ctx->escape_context = params->escape_context;
1654
1655
  /* if we have contexts, then copy them here to array */
1656
0
  if (params->contexts != NULL) {
1657
0
    unsigned int count = 0;
1658
0
    for (void *const *ctx = params->contexts; *ctx != var_expand_contexts_end; ctx++) {
1659
0
      count++;
1660
0
      array_push_back(&init_ctx->contexts, ctx);
1661
0
    }
1662
0
    i_assert(count == need_contexts);
1663
0
  } else {
1664
    /* Make sure we push some context enough to pad the context stack
1665
       to match the number of tables and providers. */
1666
0
    for (unsigned int i = 1; i < need_contexts; i++)
1667
0
      array_push_back(&init_ctx->contexts, &params->context);
1668
0
  }
1669
1670
  /* ensure everything is still good */
1671
0
  unsigned int num_tables = array_count(&init_ctx->tables);
1672
0
  unsigned int num_provs = array_count(&init_ctx->providers);
1673
0
  unsigned int num_ctx = array_count(&init_ctx->contexts);
1674
0
  i_assert(I_MAX(num_tables, num_provs) == num_ctx);
1675
0
}
1676
1677
static void
1678
settings_var_expand_init(struct settings_apply_ctx *ctx)
1679
0
{
1680
0
  struct event *event = ctx->event;
1681
0
  struct settings_var_expand_init_ctx init_ctx;
1682
0
  struct var_expand_params tmp_params;
1683
1684
0
  i_zero(&init_ctx);
1685
0
  t_array_init(&init_ctx.tables, 4);
1686
0
  t_array_init(&init_ctx.providers, 4);
1687
0
  t_array_init(&init_ctx.contexts, 4);
1688
1689
0
  while (event != NULL) {
1690
0
    settings_var_expand_t *callback =
1691
0
      event_get_ptr(event, SETTINGS_EVENT_VAR_EXPAND_CALLBACK);
1692
0
    if (callback != NULL) {
1693
0
      void *callback_context = event_get_ptr(event,
1694
0
        SETTINGS_EVENT_VAR_EXPAND_CALLBACK_CONTEXT);
1695
0
      i_zero(&tmp_params);
1696
0
      callback(callback_context, &tmp_params);
1697
0
      settings_var_expand_init_add(&init_ctx, &tmp_params);
1698
0
    } else {
1699
0
      const struct var_expand_params *params =
1700
0
        event_get_ptr(event, SETTINGS_EVENT_VAR_EXPAND_PARAMS);
1701
0
      if (params != NULL)
1702
0
        settings_var_expand_init_add(&init_ctx, params);
1703
0
    }
1704
1705
0
    event = event_get_parent(event);
1706
0
  }
1707
1708
  /* ensure everything is still good */
1709
0
  unsigned int num_tables = array_count(&init_ctx.tables);
1710
0
  unsigned int num_provs = array_count(&init_ctx.providers);
1711
0
  unsigned int num_ctx = array_count(&init_ctx.contexts);
1712
0
  i_assert(I_MAX(num_tables, num_provs) == num_ctx);
1713
1714
0
  array_append_zero(&init_ctx.tables);
1715
0
  array_append_zero(&init_ctx.providers);
1716
0
  void *context = VAR_EXPAND_CONTEXTS_END;
1717
0
  array_push_back(&init_ctx.contexts, &context);
1718
1719
0
  ctx->var_params.tables_arr = array_front(&init_ctx.tables);
1720
0
  ctx->var_params.providers_arr = array_front(&init_ctx.providers);
1721
0
  ctx->var_params.contexts = array_front(&init_ctx.contexts);
1722
0
  if (ctx->escape_func != NULL) {
1723
    /* settings_get_params()'s escape_func overrides all others */
1724
0
    ctx->var_params.escape_func = ctx->escape_func;
1725
0
    ctx->var_params.escape_context = ctx->escape_context;
1726
0
  } else {
1727
0
    ctx->var_params.escape_func = init_ctx.escape_func;
1728
0
    ctx->var_params.escape_context = init_ctx.escape_context;
1729
0
  }
1730
0
  ctx->var_params.event = ctx->event;
1731
0
}
1732
1733
static int
1734
settings_apply_override_cmp(const struct settings_apply_override *set1,
1735
          const struct settings_apply_override *set2)
1736
0
{
1737
  /* We want to sort the override similarly to filters in binary config,
1738
     i.e. primarily based on named list filter hierarchy length. This way
1739
     for example userdb namespace/inbox/mailbox/trash/auto is handled
1740
     before -o mailbox/trash/auto CLI override. */
1741
0
  int ret = (int)set2->set->filter_array_element_count -
1742
0
    (int)set1->set->filter_array_element_count;
1743
0
  if (ret != 0)
1744
0
    return ret;
1745
1746
  /* Sort by the number of named (non-list) filters. Do this only if
1747
     both overrides have named [list] filters, because we want e.g.
1748
     -o mail_path to override the default sdbox/mail_path. */
1749
0
  if (set1->set->filter_array_element_count > 0 ||
1750
0
      (set1->set->filter_element_count > 0 &&
1751
0
       set2->set->filter_element_count > 0)) {
1752
0
    ret = (int)set2->set->filter_element_count -
1753
0
      (int)set1->set->filter_element_count;
1754
0
    if (ret != 0)
1755
0
      return ret;
1756
0
  }
1757
1758
  /* Next, the override type determines the order. */
1759
0
  ret = (int)set2->set->type - (int)set1->set->type;
1760
0
  if (ret != 0)
1761
0
    return ret;
1762
1763
0
  return set2->order - set1->order;
1764
0
}
1765
1766
static int
1767
settings_override_cmp_filter_order(const struct settings_override *set,
1768
           struct settings_mmap_event_filter *set_filter)
1769
0
{
1770
0
  return (int)set->filter_array_element_count -
1771
0
    (int)set_filter->named_list_filter_count;
1772
0
}
1773
1774
static bool
1775
settings_mmap_registered_lookup_key(const char *key, enum setting_type *type_r)
1776
0
{
1777
0
  if (!array_is_created(&set_registered_infos))
1778
0
    return FALSE;
1779
1780
0
  const struct setting_parser_info *info;
1781
0
  array_foreach_elem(&set_registered_infos, info) {
1782
0
    unsigned int key_idx;
1783
0
    if (setting_parser_info_find_key(info, key, &key_idx)) {
1784
0
      *type_r = info->defines[key_idx].type;
1785
0
      return TRUE;
1786
0
    }
1787
0
  }
1788
0
  return FALSE;
1789
0
}
1790
1791
static bool
1792
settings_mmap_lookup_key(struct settings_mmap *mmap, const char *key,
1793
       enum setting_type *type_r, const void **blocks_r)
1794
0
{
1795
0
  if (mmap == NULL)
1796
0
    return settings_mmap_registered_lookup_key(key, type_r);
1797
1798
  /* Look it up from hash table */
1799
0
  uint32_t key_hash = (mmap->all_keys_hash_key_prefix ^ str_stable_hash(key)) %
1800
0
    mmap->all_keys_hash_count;
1801
0
  uint32_t rel_offset = mmap->all_keys_hash[key_hash];
1802
0
  if (rel_offset == 0)
1803
0
    return FALSE;
1804
1805
  /* Verify the name matches */
1806
0
  const char *name = CONST_PTR_OFFSET(mmap->all_keys_base, rel_offset);
1807
0
  if (strcmp(name, key) != 0)
1808
0
    return FALSE;
1809
1810
  /* Get setting type */
1811
0
  const void *p = name + strlen(name) + 1;
1812
0
  uint32_t set_type;
1813
0
  memcpy(&set_type, p, sizeof(set_type));
1814
0
  *type_r = set_type;
1815
0
  *blocks_r = CONST_PTR_OFFSET(p, sizeof(set_type));
1816
0
  return TRUE;
1817
0
}
1818
1819
static bool
1820
settings_override_key_part_find(struct settings_mmap *mmap, const char **key,
1821
        const char *last_filter_key,
1822
        const char *last_filter_value,
1823
        enum setting_type *type_r,
1824
        const void **blocks_r)
1825
0
{
1826
0
  if (last_filter_value != NULL) {
1827
0
    i_assert(last_filter_key != NULL);
1828
0
    const char *key_prefix = last_filter_key;
1829
    /* Try filter/name/key -> filter_name_key, and fallback to
1830
       filter_key. Do this before the non-prefixed check, so e.g.
1831
       inet_listener/imap/ssl won't try to change the global ssl
1832
       setting. */
1833
0
    const char *prefixed_key =
1834
0
      t_strdup_printf("%s_%s_%s", key_prefix,
1835
0
          last_filter_value, *key);
1836
0
    if (settings_mmap_lookup_key(mmap, prefixed_key, type_r, blocks_r)) {
1837
0
      *key = prefixed_key;
1838
0
      return TRUE;
1839
0
    }
1840
1841
0
    prefixed_key = t_strdup_printf("%s_%s", key_prefix, *key);
1842
0
    if (settings_mmap_lookup_key(mmap, prefixed_key, type_r, blocks_r)) {
1843
0
      *key = prefixed_key;
1844
0
      return TRUE;
1845
0
    }
1846
0
  }
1847
0
  return settings_mmap_lookup_key(mmap, *key, type_r, blocks_r);
1848
0
}
1849
1850
static bool
1851
settings_key_part_find(struct settings_apply_ctx *ctx, const char **key,
1852
           const char *last_filter_key,
1853
           const char *last_filter_value,
1854
           unsigned int *key_idx_r)
1855
0
{
1856
0
  if (last_filter_value != NULL) {
1857
0
    i_assert(last_filter_key != NULL);
1858
0
    const char *key_prefix = last_filter_key;
1859
    /* Try filter/name/key -> filter_name_key, and fallback to
1860
       filter_key. Do this before the non-prefixed check, so e.g.
1861
       inet_listener/imap/ssl won't try to change the global ssl
1862
       setting. */
1863
0
    const char *prefixed_key =
1864
0
      t_strdup_printf("%s_%s_%s", key_prefix,
1865
0
          last_filter_value, *key);
1866
0
    if (setting_parser_info_find_key(ctx->info, prefixed_key,
1867
0
             key_idx_r)) {
1868
0
      *key = prefixed_key;
1869
0
      return TRUE;
1870
0
    }
1871
1872
0
    prefixed_key = t_strdup_printf("%s_%s", key_prefix, *key);
1873
0
    if (setting_parser_info_find_key(ctx->info, prefixed_key,
1874
0
             key_idx_r)) {
1875
0
      *key = prefixed_key;
1876
0
      return TRUE;
1877
0
    }
1878
0
  }
1879
0
  return setting_parser_info_find_key(ctx->info, *key, key_idx_r);
1880
0
}
1881
1882
static int
1883
settings_override_set_blocks(struct settings_mmap *mmap,
1884
           struct settings_override *set,
1885
           const char **error_r)
1886
0
{
1887
0
  enum setting_type set_type;
1888
0
  const char *key = t_strcut(set->key, '/');
1889
0
  const void *blocks;
1890
1891
0
  if (key[0] == SETTINGS_INCLUDE_GROUP_PREFIX) {
1892
    /* Group override - we don't currently support optimizing the
1893
       block name checks. */
1894
0
    return 1;
1895
0
  }
1896
0
  if (mmap == NULL) {
1897
    /* Using only built-in settings - skip optimizations. */
1898
0
    return 1;
1899
0
  }
1900
0
  if (!settings_override_key_part_find(mmap, &key, set->last_filter_key,
1901
0
               set->last_filter_value, &set_type,
1902
0
               &blocks)) {
1903
0
    *error_r = t_strdup_printf("Unknown setting '%s' (in %s)",
1904
0
             key, set->orig_key);
1905
0
    return -1;
1906
0
  }
1907
1908
0
  uint32_t i, count, block_idx;
1909
0
  memcpy(&count, blocks, sizeof(count));
1910
0
  blocks = CONST_PTR_OFFSET(blocks, sizeof(count));
1911
1912
0
  if (count == 0) {
1913
0
    *error_r = t_strdup_printf("BUG: Setting %s has no blocks", key);
1914
0
    return -1;
1915
0
  }
1916
1917
0
  const char **block_names = p_new(set->pool, const char *, count + 1);
1918
0
  for (i = 0; i < count; i++) {
1919
0
    memcpy(&block_idx, blocks, sizeof(block_idx));
1920
0
    blocks = CONST_PTR_OFFSET(blocks, sizeof(block_idx));
1921
1922
0
    if (block_idx >= mmap->block_names_count) {
1923
0
      *error_r = t_strdup_printf(
1924
0
        "BUG: Setting %s record points to nonexistent block index %u",
1925
0
        key, block_idx);
1926
0
      return -1;
1927
0
    }
1928
1929
0
    block_names[i] =
1930
0
      CONST_PTR_OFFSET(mmap->all_keys_base,
1931
0
           mmap->block_names_rel_offsets[block_idx]);
1932
0
  }
1933
0
  set->block_names = block_names;
1934
0
  return 1;
1935
0
}
1936
1937
static bool setting_override_match_info(struct settings_apply_ctx *ctx,
1938
          struct settings_override *set)
1939
0
{
1940
0
  if (set->block_names == NULL) {
1941
    /* Optimization disabled. */
1942
0
    return TRUE;
1943
0
  }
1944
0
  for (unsigned int i = 0; set->block_names[i] != NULL; i++) {
1945
0
    if (strcmp(set->block_names[i], ctx->info->name) == 0)
1946
0
      return TRUE;
1947
0
  }
1948
0
  return FALSE;
1949
0
}
1950
1951
static int
1952
settings_override_filter_match(struct settings_apply_ctx *ctx,
1953
             struct settings_override *set,
1954
             const char **error_r)
1955
0
{
1956
0
  const struct failure_context failure_ctx = {
1957
0
    .type = LOG_TYPE_DEBUG
1958
0
  };
1959
0
  const char *p, *error;
1960
1961
  /* check if the filter is already set */
1962
0
  if (set->filter != NULL) {
1963
0
    if (set->filter == EVENT_FILTER_MATCH_NEVER)
1964
0
      return 0;
1965
0
    if (!setting_override_match_info(ctx, set))
1966
0
      return 0;
1967
0
    if (set->filter == EVENT_FILTER_MATCH_ALWAYS)
1968
0
      return 1;
1969
0
    return event_filter_match(set->filter, ctx->event,
1970
0
            &failure_ctx) ? 1 : 0;
1971
0
  }
1972
1973
0
  if (str_begins(set->key, "*"SETTINGS_SEPARATOR_S, &set->key)) {
1974
    /* always match, also for any named list filters */
1975
0
    int ret = settings_override_set_blocks(ctx->instance->mmap,
1976
0
                   set, error_r);
1977
0
    if (ret <= 0)
1978
0
      return ret;
1979
    /* Sort this as the first */
1980
0
    set->filter_array_element_count = INT_MAX;
1981
0
    set->filter = EVENT_FILTER_MATCH_ALWAYS;
1982
0
    return setting_override_match_info(ctx, set) ? 1 : 0;
1983
0
  }
1984
1985
0
  string_t *filter_string = NULL;
1986
0
  const char *last_filter_key = NULL;
1987
0
  const char *last_filter_value = NULL;
1988
0
  while ((p = strchr(set->key, SETTINGS_SEPARATOR)) != NULL) {
1989
0
    const char *part = t_strdup_until(set->key, p);
1990
0
    enum setting_type set_type;
1991
0
    const void *blocks ATTR_UNUSED;
1992
1993
0
    if (!settings_override_key_part_find(ctx->instance->mmap, &part,
1994
0
                 last_filter_key,
1995
0
                 last_filter_value,
1996
0
                 &set_type, &blocks)) {
1997
0
      *error_r = t_strdup_printf("Unknown setting '%s' (in %s)",
1998
0
               part, set->orig_key);
1999
0
      return -1;
2000
0
    }
2001
2002
0
    if (set_type == SET_STRLIST || set_type == SET_BOOLLIST)
2003
0
      break;
2004
2005
0
    if (filter_string == NULL)
2006
0
      filter_string = t_str_new(64);
2007
0
    else
2008
0
      str_append(filter_string, " AND ");
2009
0
    switch (set_type) {
2010
0
    case SET_FILTER_NAME:
2011
0
      last_filter_key = part;
2012
0
      last_filter_value = NULL;
2013
0
      str_printfa(filter_string, SETTINGS_EVENT_FILTER_NAME"=\"%s\"",
2014
0
            wildcard_str_escape(last_filter_key));
2015
0
      set->filter_element_count++;
2016
0
      break;
2017
0
    case SET_FILTER_ARRAY: {
2018
0
      const char *value = p + 1;
2019
0
      p = strchr(value, SETTINGS_SEPARATOR);
2020
0
      if (p == NULL) {
2021
0
        *error_r = t_strdup_printf(
2022
0
          "Setting override %s is missing filter name child element ('/child' expected)",
2023
0
          set->key);
2024
0
        return -1;
2025
0
      }
2026
0
      last_filter_key = part;
2027
0
      last_filter_value = t_strdup_until(value, p);
2028
0
      str_printfa(filter_string, SETTINGS_EVENT_FILTER_NAME"=\"%s/%s\"",
2029
0
            last_filter_key, wildcard_str_escape(settings_section_escape(last_filter_value)));
2030
0
      set->filter_array_element_count++;
2031
0
      break;
2032
0
    }
2033
0
    default:
2034
0
      *error_r = t_strdup_printf(
2035
0
        "Setting override %s type doesn't support child elements in the path ('/' not expected)",
2036
0
        set->key);
2037
0
      return -1;
2038
0
    }
2039
0
    set->key = p + 1;
2040
0
  }
2041
2042
0
  if (set->last_filter_key != last_filter_key)
2043
0
    set->last_filter_key = p_strdup(set->pool, last_filter_key);
2044
0
  if (set->last_filter_value != last_filter_value)
2045
0
    set->last_filter_value = p_strdup(set->pool, last_filter_value);
2046
2047
0
  int ret = settings_override_set_blocks(ctx->instance->mmap, set, error_r);
2048
0
  if (ret <= 0)
2049
0
    return ret;
2050
2051
0
  if (filter_string == NULL)
2052
0
    set->filter = EVENT_FILTER_MATCH_ALWAYS;
2053
0
  else {
2054
0
    set->filter = event_filter_create_with_pool(set->pool);
2055
0
    if (event_filter_parse_case_sensitive(str_c(filter_string),
2056
0
                  set->filter, &error) < 0) {
2057
0
      i_panic("BUG: Failed to create event filter filter for %s: %s (%s)",
2058
0
        set->orig_key, error, str_c(filter_string));
2059
0
    }
2060
0
    pool_ref(set->pool);
2061
0
  }
2062
2063
0
  if (!setting_override_match_info(ctx, set))
2064
0
    return 0;
2065
0
  return (set->filter == EVENT_FILTER_MATCH_ALWAYS ||
2066
0
    event_filter_match(set->filter, ctx->event, &failure_ctx)) ? 1 : 0;
2067
0
}
2068
2069
static bool settings_override_find_filter_check(struct settings_apply_ctx *ctx,
2070
            struct settings_override *set)
2071
0
{
2072
0
  static const struct failure_context failure_ctx = {
2073
0
    .type = LOG_TYPE_DEBUG
2074
0
  };
2075
0
  return ctx->filter_key != NULL && set->last_filter_key != NULL &&
2076
0
    strcmp(ctx->filter_key, set->last_filter_key) == 0 &&
2077
0
    null_strcmp(ctx->filter_value, set->last_filter_value) == 0 &&
2078
2079
0
    set->filter != EVENT_FILTER_MATCH_NEVER &&
2080
0
    set->filter != EVENT_FILTER_MATCH_ALWAYS &&
2081
0
    event_filter_match(set->filter, ctx->event, &failure_ctx);
2082
0
}
2083
2084
static bool settings_overrides_find_filter(struct settings_apply_ctx *ctx)
2085
0
{
2086
  /* We've optimized skipping overrides that don't match the current
2087
     info. Now it looks like a filter lookup didn't find any settings.
2088
     But it's possible that there are settings for the filter in
2089
     overrides, just for different infos. Check if this is the case. */
2090
0
  struct settings_override *set;
2091
0
  if (array_is_created(&ctx->instance->overrides)) {
2092
0
    array_foreach_modifiable(&ctx->instance->overrides, set) {
2093
0
      if (settings_override_find_filter_check(ctx, set))
2094
0
        return TRUE;
2095
0
    }
2096
0
  }
2097
0
  if (array_is_created(&ctx->root->overrides)) {
2098
0
    array_foreach_modifiable(&ctx->root->overrides, set) {
2099
0
      if (settings_override_find_filter_check(ctx, set))
2100
0
        return TRUE;
2101
0
    }
2102
0
  }
2103
0
  return FALSE;
2104
0
}
2105
2106
static int
2107
settings_override_get_value(struct settings_apply_ctx *ctx,
2108
          const struct settings_override *set,
2109
          const char **_key, unsigned int *key_idx_r,
2110
          const char **value_r)
2111
0
{
2112
0
  const char *key = *_key;
2113
0
  unsigned int key_idx = UINT_MAX;
2114
2115
0
  if (!settings_key_part_find(ctx, &key, set->last_filter_key,
2116
0
            set->last_filter_value, &key_idx))
2117
0
    key_idx = UINT_MAX;
2118
2119
0
  if (key_idx == UINT_MAX)
2120
0
    return 0;
2121
2122
  /* remove alias */
2123
0
  const char *list = strchr(key, SETTINGS_SEPARATOR);
2124
0
  if (list == NULL)
2125
0
    key = ctx->info->defines[key_idx].key;
2126
0
  else
2127
0
    key = t_strconcat(ctx->info->defines[key_idx].key, list, NULL);
2128
2129
0
  if (!set->append ||
2130
0
      !setting_type_is_str_vars(ctx->info->defines[key_idx].type)) {
2131
0
    if (set->append && ctx->info->defines[key_idx].type != SET_FILTER_ARRAY)
2132
0
      *_key = t_strconcat(key, SETTINGS_APPEND_KEY_SUFFIX, NULL);
2133
0
    else
2134
0
      *_key = key;
2135
0
    *key_idx_r = key_idx;
2136
2137
0
    const char *inline_value;
2138
0
    if (!str_begins(set->value, SET_FILE_INLINE_PREFIX,
2139
0
        &inline_value))
2140
0
      *value_r = set->value;
2141
0
    else
2142
0
      *value_r = t_strconcat("\n", inline_value, NULL);
2143
0
    return 1;
2144
0
  }
2145
2146
0
  const char *const *strp =
2147
0
    PTR_OFFSET(ctx->set_struct, ctx->info->defines[key_idx].offset);
2148
0
  *_key = key;
2149
0
  *key_idx_r = key_idx;
2150
0
  *value_r = t_strconcat(*strp, set->value, NULL);
2151
0
  return 1;
2152
0
}
2153
2154
static int
2155
settings_instance_override_add_default(struct settings_apply_ctx *ctx,
2156
               struct settings_override *array_set,
2157
               unsigned int key_idx,
2158
               const char **error_r)
2159
0
{
2160
0
  const struct setting_define *array_def =
2161
0
    &ctx->info->defines[key_idx];
2162
2163
0
  i_assert(array_set->overrides_array != NULL);
2164
0
  array_set->array_default_added = TRUE;
2165
2166
  /* As an example we could be here because of
2167
     -o namespace/inbox/mailbox+=foo,bar override (= array_set):
2168
2169
     * array_def points to mailbox's setting_define
2170
     * We're going to add namespace/inbox/mailbox/foo/mailbox_name=foo
2171
       and namespace/inbox/mailbox/bar/mailbox_name=bar to avoid having
2172
       to explicitly define them.
2173
     * These are SETTINGS_OVERRIDE_TYPE_DEFAULT, so they will be used
2174
       only if the configuration file didn't already specify a different
2175
       mailbox_name for these filters.
2176
     * We're going to have to build the event filter ourself here,
2177
       because it's most likely too late for it to be left later. The
2178
       next settings_get_filter() could be trying to look up this filter
2179
       and it won't know enough to build the event filter.
2180
  */
2181
0
  const char *const *items =
2182
0
    t_strsplit(array_set->value, SETTINGS_FILTER_ARRAY_SEPARATORS);
2183
0
  for (unsigned int i = 0; items[i] != NULL; i++) {
2184
0
    struct settings_override *set =
2185
0
      array_append_space(array_set->overrides_array);
2186
0
    set->pool = array_set->pool;
2187
0
    set->type = SETTINGS_OVERRIDE_TYPE_DEFAULT;
2188
2189
0
    set->orig_key = p_strdup_printf(set->pool, "%s/%s/%s",
2190
0
      array_set->orig_key, items[i],
2191
0
      array_def->filter_array_field_name);
2192
    /* We're building the full event filter, so jump forward in
2193
       the key path until the last field. */
2194
0
    set->key = array_def->filter_array_field_name;
2195
0
    set->filter_array_element_count =
2196
0
      array_set->filter_array_element_count;
2197
0
    set->filter_element_count =
2198
0
      array_set->filter_element_count;
2199
0
    set->value = p_strdup(set->pool, items[i]);
2200
2201
    /* Get the final key we want to use in the event filter.
2202
       For example "mailbox", which in this special case gets
2203
       translated to "mailbox_subname". */
2204
0
    const char *filter_key = strrchr(array_set->orig_key, '/');
2205
0
    if (filter_key != NULL)
2206
0
      filter_key++;
2207
0
    else
2208
0
      filter_key = array_set->orig_key;
2209
2210
    /* Build the final event filter. */
2211
0
    const char *filter_string = t_strdup_printf(
2212
0
      SETTINGS_EVENT_FILTER_NAME"=\"%s/%s\"",
2213
0
      filter_key, wildcard_str_escape(settings_section_escape(items[i])));
2214
0
    const char *error;
2215
2216
0
    if (settings_override_set_blocks(ctx->instance->mmap,
2217
0
             set, error_r) < 0)
2218
0
      return -1;
2219
2220
0
    set->filter = event_filter_create_with_pool(set->pool);
2221
0
    pool_ref(set->pool);
2222
0
    if (event_filter_parse_case_sensitive(filter_string,
2223
0
                  set->filter, &error) < 0) {
2224
0
      i_panic("BUG: Failed to create event filter for %s: %s (%s)",
2225
0
        set->orig_key, error, filter_string);
2226
0
    }
2227
0
    if (array_set->filter != EVENT_FILTER_MATCH_ALWAYS) {
2228
      /* Merge the final event filter with the parent
2229
         SET_FILTER_ARRAY's event filter. */
2230
0
      event_filter_merge(set->filter, array_set->filter,
2231
0
             EVENT_FILTER_MERGE_OP_AND);
2232
0
    }
2233
0
  }
2234
0
  return 0;
2235
0
}
2236
2237
static int settings_apply_add_override(struct settings_apply_ctx *ctx,
2238
               struct settings_override *set,
2239
               const char **error_r)
2240
0
{
2241
0
  int ret;
2242
0
  T_BEGIN {
2243
0
    ret = settings_override_filter_match(ctx, set, error_r);
2244
0
  } T_END_PASS_STR_IF(ret < 0, error_r);
2245
0
  if (ret <= 0)
2246
0
    return ret;
2247
2248
0
  struct settings_apply_override *override =
2249
0
    array_append_space(&ctx->overrides);
2250
0
  override->set = set;
2251
0
  override->order = array_count(&ctx->overrides);
2252
0
  return 1;
2253
0
}
2254
2255
static void
2256
settings_instance_overrides_add_filters(struct settings_apply_ctx *ctx,
2257
          const struct setting_parser_info *info)
2258
0
{
2259
0
  const struct setting_keyvalue *defaults = info->default_settings;
2260
0
  struct settings_override *set;
2261
0
  const char *error;
2262
0
  int ret;
2263
2264
0
  if (defaults == NULL)
2265
0
    return;
2266
0
  for (unsigned int i = 0; defaults[i].key != NULL; i++) {
2267
0
    set = p_new(ctx->temp_pool, struct settings_override, 1);
2268
0
    set->pool = ctx->temp_pool;
2269
0
    set->type = SETTINGS_OVERRIDE_TYPE_DEFAULT;
2270
0
    set->key = set->orig_key = defaults[i].key;
2271
0
    set->value = defaults[i].value;
2272
0
    if ((ret = settings_apply_add_override(ctx, set, &error)) < 0)
2273
0
      i_panic("Applying default settings failed: %s", error);
2274
0
    if (ret == 0)
2275
0
      settings_override_free(set);
2276
0
  }
2277
0
}
2278
2279
static int
2280
settings_instance_override_init(struct settings_apply_ctx *ctx,
2281
        const char **error_r)
2282
0
{
2283
0
  struct settings_override *set;
2284
0
  bool have_2nd_defaults = FALSE;
2285
2286
0
  if (ctx->instance->mmap == NULL) {
2287
    /* For unit tests, auto-register the looked up info */
2288
0
    settings_info_register(ctx->info);
2289
0
  }
2290
2291
0
  t_array_init(&ctx->overrides, 64);
2292
0
  if (array_is_created(&ctx->instance->overrides)) {
2293
0
    array_foreach_modifiable(&ctx->instance->overrides, set) {
2294
0
      if (set->type == SETTINGS_OVERRIDE_TYPE_2ND_DEFAULT)
2295
0
        have_2nd_defaults = TRUE;
2296
0
      if (settings_apply_add_override(ctx, set, error_r) < 0)
2297
0
        return -1;
2298
0
    }
2299
0
  }
2300
0
  if (array_is_created(&ctx->root->overrides)) {
2301
0
    array_foreach_modifiable(&ctx->root->overrides, set) {
2302
0
      if (set->type == SETTINGS_OVERRIDE_TYPE_2ND_DEFAULT)
2303
0
        have_2nd_defaults = TRUE;
2304
0
      if (settings_apply_add_override(ctx, set, error_r) < 0)
2305
0
        return -1;
2306
0
    }
2307
0
  }
2308
0
  if ((ctx->instance->mmap == NULL || have_2nd_defaults) &&
2309
0
      array_is_created(&set_registered_infos)) {
2310
    /* a) No configuration - default_settings won't be
2311
       applied unless we add them here also. This isn't for any
2312
       production use, so performance doesn't matter.
2313
2314
       b) SETTINGS_OVERRIDE_TYPE_2ND_DEFAULT has been used. The
2315
       idea is that unless SETTINGS_OVERRIDE_TYPE_2ND_CLI_PARAM has
2316
       overridden it, the value should be the default. This works
2317
       for the defaults in the struct without extra code, but if
2318
       the default comes from setting_parser_info.default_settings,
2319
       we'll need to add those into overrides as
2320
       SETTINGS_OVERRIDE_TYPE_DEFAULT. We really only need to
2321
       add those specific keys that have
2322
       SETTINGS_OVERRIDE_TYPE_2ND_DEFAULT, but it's a bit
2323
       troublesome to check which ones have it. It's not harmful
2324
       to have other settings there as well, since for other
2325
       settings the SETTINGS_OVERRIDE_TYPE_DEFAULT overrides are
2326
       never even processed, because the final settings come from
2327
       the binary config. */
2328
0
    const struct setting_parser_info *info;
2329
0
    ctx->temp_pool = pool_alloconly_create("settings temp pool", 256);
2330
0
    array_foreach_elem(&set_registered_infos, info)
2331
0
      settings_instance_overrides_add_filters(ctx, info);
2332
0
  }
2333
  /* sort overrides so that the most specific ones are first */
2334
0
  array_sort(&ctx->overrides, settings_apply_override_cmp);
2335
0
  return 0;
2336
0
}
2337
2338
static void
2339
settings_apply_ctx_overrides_deinit(struct settings_apply_ctx *ctx)
2340
0
{
2341
0
  struct settings_apply_override *set;
2342
2343
0
  array_foreach_modifiable(&ctx->overrides, set) {
2344
0
    if (set->set != NULL && set->set->pool == ctx->temp_pool)
2345
0
      settings_override_free(set->set);
2346
0
  }
2347
0
}
2348
2349
static void
2350
settings_include_group_add_or_update(ARRAY_TYPE(settings_group) *include_groups,
2351
             const struct settings_override *set)
2352
0
{
2353
0
  struct settings_group *include_group;
2354
2355
  /* we assume that the key/value pointers in "set" exist at least as
2356
     long as "includes" array */
2357
0
  array_foreach_modifiable(include_groups, include_group) {
2358
0
    if (strcmp(include_group->label, set->key + 1) == 0) {
2359
0
      include_group->name = set->value;
2360
0
      return;
2361
0
    }
2362
0
  }
2363
0
  include_group = array_append_space(include_groups);
2364
0
  include_group->label = set->key + 1;
2365
0
  include_group->name = set->value;
2366
0
}
2367
2368
static int
2369
settings_instance_override(struct settings_apply_ctx *ctx,
2370
         struct settings_mmap_event_filter *set_filter,
2371
         bool *defaults, const char **error_r)
2372
0
{
2373
0
  struct settings_apply_override *override;
2374
0
  struct settings_override *set;
2375
0
  enum setting_apply_flags apply_flags = SETTING_APPLY_FLAG_OVERRIDE |
2376
0
    ((ctx->flags & SETTINGS_GET_FLAG_NO_EXPAND) == 0 ? 0 :
2377
0
     SETTING_APPLY_FLAG_NO_EXPAND);
2378
2379
0
  bool seen_defaults = FALSE;
2380
0
  bool seen_filter = FALSE;
2381
0
  array_foreach_modifiable(&ctx->overrides, override) {
2382
0
    if (override->set == NULL)
2383
0
      continue; /* already applied */
2384
0
    set = override->set;
2385
2386
0
    unsigned int key_idx;
2387
0
    int ret;
2388
2389
    /* If we're being called while applying filters, only apply
2390
       the overrides that have a matching filter. This preserves
2391
       the expected order in which settings are applied. */
2392
0
    if (set_filter->filter != EVENT_FILTER_MATCH_ALWAYS &&
2393
0
        settings_override_cmp_filter_order(set, set_filter) < 0)
2394
0
      break;
2395
2396
0
    if (set->type == SETTINGS_OVERRIDE_TYPE_DEFAULT) {
2397
0
      seen_defaults = TRUE;
2398
0
      if (!*defaults)
2399
0
        continue;
2400
0
    }
2401
2402
0
    if (ctx->filter_key != NULL && set->last_filter_key != NULL &&
2403
0
        strcmp(ctx->filter_key, set->last_filter_key) == 0 &&
2404
0
        null_strcmp(ctx->filter_value, set->last_filter_value) == 0)
2405
0
      seen_filter = TRUE;
2406
2407
    /* Set key only after settings_override_filter_match() has
2408
       potentially changed it. */
2409
0
    const char *key = set->key, *value;
2410
0
    if (key[0] == SETTINGS_INCLUDE_GROUP_PREFIX) {
2411
0
      settings_include_group_add_or_update(
2412
0
        &ctx->include_groups, set);
2413
0
      continue;
2414
0
    }
2415
0
    ret = settings_override_get_value(ctx, set, &key,
2416
0
              &key_idx, &value);
2417
0
    if (ret < 0)
2418
0
      return -1;
2419
0
    if (ret == 0) {
2420
      /* setting doesn't exist in this info */
2421
0
      continue;
2422
0
    }
2423
0
    bool value_needs_dup = (value != set->value);
2424
0
    bool track_seen = TRUE;
2425
0
    if (ctx->info->defines[key_idx].type == SET_FILTER_ARRAY) {
2426
0
      track_seen = FALSE;
2427
      /* Last part is a named list filter. Permanently store
2428
         pointer to the definition for this setting, which
2429
         allows future override lookups to fill the default
2430
         array name setting. */
2431
0
      if (!set->array_default_added) {
2432
0
        if (settings_instance_override_add_default(ctx,
2433
0
            set, key_idx, error_r) < 0)
2434
0
          return -1;
2435
0
      }
2436
0
    } else if (ctx->info->defines[key_idx].type == SET_STRLIST ||
2437
0
         ctx->info->defines[key_idx].type == SET_BOOLLIST) {
2438
0
      const char *suffix;
2439
0
      if (!str_begins(key, ctx->info->defines[key_idx].key, &suffix))
2440
0
        i_unreached();
2441
0
      if (suffix[0] == '/' &&
2442
0
          set->type == SETTINGS_OVERRIDE_TYPE_DEFAULT) {
2443
        /* Expand %variables in the key, but only for
2444
           default overrides - the same way the value is
2445
           expanded below. -o and userdb overrides keep
2446
           their keys (and values) literal. Done before
2447
           has_key() so dedup uses the final key. */
2448
0
        const char *exp_key = suffix + 1, *error;
2449
0
        if (settings_var_expand(ctx, key_idx, &exp_key,
2450
0
              &error) < 0) {
2451
0
          *error_r = t_strdup_printf(
2452
0
            "Failed to expand default setting %s key variables: %s",
2453
0
            key, error);
2454
0
          return -1;
2455
0
        }
2456
0
        key = t_strconcat(ctx->info->defines[key_idx].key,
2457
0
              "/", exp_key, NULL);
2458
0
        suffix = key + strlen(ctx->info->defines[key_idx].key);
2459
0
      }
2460
0
      if (suffix[0] != '/') {
2461
        /* replace full boollist setting
2462
           (invalid for strlist) */
2463
0
        i_assert(suffix[0] == '\0');
2464
0
      } else if (settings_parse_list_has_key(ctx->parser,
2465
0
          key_idx,
2466
0
          settings_section_unescape(suffix + 1)))
2467
0
        continue;
2468
0
      else
2469
0
        track_seen = FALSE;
2470
0
    }
2471
0
    if (track_seen) {
2472
0
      enum set_seen_type *set_seenp =
2473
0
        array_idx_get_space(&ctx->set_seen, key_idx);
2474
0
      switch (*set_seenp) {
2475
0
      case SET_SEEN_NO:
2476
0
        break;
2477
0
      case SET_SEEN_YES:
2478
        /* already set - skip */
2479
0
        continue;
2480
0
      case SET_SEEN_DEFAULT:
2481
        /* already seen, but still apply defaults */
2482
0
        if (set->type != SETTINGS_OVERRIDE_TYPE_DEFAULT)
2483
0
          continue;
2484
0
        break;
2485
0
      }
2486
0
      if (set->type == SETTINGS_OVERRIDE_TYPE_2ND_DEFAULT)
2487
0
        *set_seenp = SET_SEEN_DEFAULT;
2488
0
      else
2489
0
        *set_seenp = SET_SEEN_YES;
2490
0
    }
2491
    /* skip this setting the next time */
2492
0
    override->set = NULL;
2493
0
    if (set->pool == ctx->temp_pool)
2494
0
      settings_override_free(set);
2495
2496
0
    if (set->type == SETTINGS_OVERRIDE_TYPE_DEFAULT) {
2497
      /* Expand %variables only for default settings.
2498
         These defaults are usually handled already by the
2499
         config process, but we get here with -O parameter
2500
         or with SETTINGS_OVERRIDE_TYPE_2ND_DEFAULT. */
2501
0
      const char *error;
2502
0
      ret = settings_var_expand(ctx, key_idx, &value, &error);
2503
0
      if (ret < 0) {
2504
0
        *error_r = t_strdup_printf(
2505
0
          "Failed to expand default setting %s=%s variables: %s",
2506
0
          key, value, error);
2507
0
        return -1;
2508
0
      }
2509
0
      if (ret > 0) {
2510
        /* value was already strdup()ed */
2511
0
        value_needs_dup = FALSE;
2512
0
      }
2513
0
    } else if ((ctx->info->defines[key_idx].type == SET_PATH_FILE ||
2514
0
          ctx->info->defines[key_idx].type == SET_PATH_DIR) &&
2515
0
         (ctx->flags & SETTINGS_GET_FLAG_NO_EXPAND) == 0) {
2516
0
      size_t value_len = strlen(value);
2517
0
      if (ctx->info->defines[key_idx].type == SET_PATH_DIR &&
2518
0
          value_len > 0 && value[value_len-1] == '/') {
2519
        /* drop trailing '/' */
2520
0
        value = t_strndup(value, value_len - 1);
2521
0
        value_needs_dup = TRUE;
2522
0
      }
2523
0
      if (str_begins_with(value, "~/") ||
2524
0
          strcmp(value, "~") == 0) {
2525
        /* Expand only the ~/ prefix to the %{home}
2526
           variable's value. Unlike default settings,
2527
           the rest of the override value is kept
2528
           literal without %variable expansion. */
2529
0
        const char *error;
2530
0
        string_t *home = t_str_new(64);
2531
0
        if (var_expand(home, "%{home}", &ctx->var_params,
2532
0
                 &error) < 0) {
2533
0
          if ((ctx->flags & SETTINGS_GET_FLAG_FAKE_EXPAND) == 0) {
2534
0
            *error_r = t_strdup_printf(
2535
0
              "Failed to expand %s=%s home directory: %s",
2536
0
              key, value, error);
2537
0
            return -1;
2538
0
          }
2539
0
        } else {
2540
0
          str_append(home, value + 1);
2541
0
          value = str_c(home);
2542
0
          value_needs_dup = TRUE;
2543
0
        }
2544
0
      }
2545
0
    }
2546
0
    if (ctx->info->defines[key_idx].type == SET_FILTER_ARRAY &&
2547
0
        set->type <= SETTINGS_OVERRIDE_TYPE_CLI_PARAM &&
2548
0
        str_begins_with(value, "__")) {
2549
0
      *error_r = t_strdup_printf(
2550
0
        "Named list filter name must not begin with '__': %s",
2551
0
        value);
2552
0
      return -1;
2553
0
    }
2554
2555
0
    if (value_needs_dup)
2556
0
      value = p_strdup(&ctx->mpool->pool, value);
2557
0
    else if (value == set->value) {
2558
      /* Add explicit reference to instance->pool, which is
2559
         kept by the settings struct's pool. This allows
2560
         settings to survive even if the instance is freed.
2561
2562
         If there is no instance pool, it means there are
2563
         only CLI_PARAM settings, which are allocated from
2564
         FIXME: should figure out some efficient way how to
2565
         store them. */
2566
0
      if (array_is_created(&ctx->mpool->pool.external_refs))
2567
0
        i_assert(array_idx_elem(&ctx->mpool->pool.external_refs, 0) == ctx->instance->pool);
2568
0
      else if (ctx->instance->pool != NULL)
2569
0
        pool_add_external_ref(&ctx->mpool->pool, ctx->instance->pool);
2570
0
    }
2571
    /* An empty built-in default for a setting that can't be empty
2572
       (e.g. a number or time) means "no default": leave the value
2573
       to be inherited from a less specific filter instead of
2574
       failing. This lets a named filter keep a default-settings
2575
       entry - so settings-history can override the value for old
2576
       config versions - without forcing that value for current
2577
       versions. The config process handles this equivalently in
2578
       config_apply_exact_line(). */
2579
0
    bool empty_default =
2580
0
      set->type == SETTINGS_OVERRIDE_TYPE_DEFAULT &&
2581
0
      value[0] == '\0';
2582
0
    if (ctx->info->setting_apply != NULL &&
2583
0
        !ctx->info->setting_apply(ctx->event, ctx->set_struct, key,
2584
0
                &value, apply_flags, error_r)) {
2585
0
      if (empty_default)
2586
0
        continue;
2587
0
      *error_r = t_strdup_printf(
2588
0
        "Failed to override configuration from %s: "
2589
0
        "Invalid %s=%s: %s",
2590
0
        settings_override_type_names[set->type],
2591
0
        key, value, *error_r);
2592
0
      return -1;
2593
0
    }
2594
0
    if (settings_parse_keyidx_value_nodup(ctx->parser, key_idx, key,
2595
0
                  value) < 0) {
2596
0
      if (empty_default)
2597
0
        continue;
2598
0
      *error_r = t_strdup_printf(
2599
0
        "Failed to override configuration from %s: "
2600
0
        "Invalid %s=%s: %s",
2601
0
        settings_override_type_names[set->type],
2602
0
        key, value, settings_parser_get_error(ctx->parser));
2603
0
      return -1;
2604
0
    }
2605
2606
0
    if (!set->append &&
2607
0
        ctx->info->defines[key_idx].type == SET_FILTER_ARRAY) {
2608
      /* The named list filter is filled in reverse order.
2609
         Mark it now as "stopped", so following filters won't
2610
         try to insert anything more into it. */
2611
0
      settings_parse_array_stop(ctx->parser, key_idx);
2612
0
    }
2613
0
  }
2614
0
  *defaults = seen_defaults;
2615
0
  return seen_filter ? 1 : 0;
2616
0
}
2617
2618
static int
2619
settings_instance_get(struct settings_apply_ctx *ctx,
2620
          const char *source_filename,
2621
          unsigned int source_linenum,
2622
          const void **set_r, const char **error_r)
2623
0
{
2624
0
  const char *error;
2625
0
  bool seen_filter = FALSE;
2626
0
  int ret = 0;
2627
2628
0
  i_assert(ctx->info->pool_offset1 != 0);
2629
2630
0
  *set_r = NULL;
2631
2632
0
  if (event_find_field_recursive(ctx->event, "protocol") == NULL)
2633
0
    event_add_str(ctx->event, "protocol", ctx->root->protocol_name);
2634
2635
0
  ctx->mpool = settings_mmap_pool_create(ctx->root, ctx->instance->mmap,
2636
0
                 source_filename, source_linenum);
2637
0
  pool_t set_pool = &ctx->mpool->pool;
2638
0
  ctx->parser = settings_parser_init(set_pool, ctx->info,
2639
0
             SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS |
2640
0
             SETTINGS_PARSER_FLAG_INSERT_FILTERS);
2641
2642
  /* Set the pool early on before any callbacks are called. */
2643
0
  ctx->set_struct = settings_parser_get_set(ctx->parser);
2644
0
  pool_t *pool_p = PTR_OFFSET(ctx->set_struct,
2645
0
            ctx->info->pool_offset1 - 1);
2646
0
  *pool_p = set_pool;
2647
2648
0
  t_array_init(&ctx->include_groups, 4);
2649
0
  ctx->str = str_new(default_pool, 256);
2650
0
  i_array_init(&ctx->set_seen, 64);
2651
0
  if ((ctx->flags & SETTINGS_GET_FLAG_NO_EXPAND) == 0 &&
2652
0
      (ctx->flags & SETTINGS_GET_FLAG_FAKE_EXPAND) == 0)
2653
0
    settings_var_expand_init(ctx);
2654
2655
0
  if (settings_instance_override_init(ctx, error_r) < 0)
2656
0
    ret = -1;
2657
0
  else if (ctx->instance->mmap != NULL) {
2658
0
    ret = settings_mmap_apply(ctx, &error);
2659
0
    if (ret < 0) {
2660
0
      *error_r = t_strdup_printf(
2661
0
        "Failed to parse configuration: %s", error);
2662
0
    }
2663
0
  } else {
2664
    /* No configuration file - apply all overrides */
2665
0
    bool defaults = TRUE;
2666
0
    struct settings_mmap_event_filter set_filter = {
2667
0
    };
2668
0
    ret = settings_instance_override(ctx, &set_filter,
2669
0
             &defaults, error_r);
2670
0
  }
2671
0
  if (ret > 0)
2672
0
    seen_filter = TRUE;
2673
0
  settings_apply_ctx_overrides_deinit(ctx);
2674
2675
0
  if (ret >= 0)
2676
0
    ret = settings_mmap_apply_defaults(ctx, error_r);
2677
0
  if (ret < 0) {
2678
0
    pool_unref(&set_pool);
2679
0
    return -1;
2680
0
  }
2681
2682
0
  if (ctx->filter_key != NULL && !seen_filter &&
2683
0
      ctx->filter_name_required &&
2684
0
      !settings_overrides_find_filter(ctx)) {
2685
0
    pool_unref(&set_pool);
2686
0
    return 0;
2687
0
  }
2688
2689
0
  if ((ctx->flags & SETTINGS_GET_FLAG_NO_CHECK) == 0) {
2690
0
    if (!settings_check(ctx->event, ctx->info, *pool_p,
2691
0
            ctx->set_struct, error_r)) {
2692
0
      *error_r = t_strdup_printf("Invalid settings: %s",
2693
0
               *error_r);
2694
0
      pool_unref(&set_pool);
2695
0
      return -1;
2696
0
    }
2697
0
  }
2698
2699
0
  *set_r = ctx->set_struct;
2700
0
  return 1;
2701
0
}
2702
2703
static void
2704
settings_event_convert_filter_names(struct event *src_event, struct event *dest_event)
2705
0
{
2706
0
  const char *filter_name =
2707
0
    event_get_ptr(src_event, SETTINGS_EVENT_FILTER_NAME);
2708
0
  if (filter_name == NULL)
2709
0
    return;
2710
0
  event_strlist_append(dest_event, SETTINGS_EVENT_FILTER_NAME,
2711
0
           filter_name);
2712
2713
  /* usually there is just one, continue fast path so see if there is a
2714
     2nd one. */
2715
0
  filter_name = event_get_ptr(src_event, SETTINGS_EVENT_FILTER_NAME"2");
2716
0
  if (filter_name == NULL)
2717
0
    return;
2718
0
  event_strlist_append(dest_event, SETTINGS_EVENT_FILTER_NAME,
2719
0
           filter_name);
2720
2721
  /* check the rest: */
2722
0
  string_t *key = t_str_new(strlen(SETTINGS_EVENT_FILTER_NAME) + 1);
2723
0
  str_append(key, SETTINGS_EVENT_FILTER_NAME);
2724
0
  for (unsigned int i = 3;; i++) {
2725
0
    str_truncate(key, strlen(SETTINGS_EVENT_FILTER_NAME));
2726
0
    str_printfa(key, "%u", i);
2727
0
    filter_name = event_get_ptr(src_event, str_c(key));
2728
0
    if (filter_name == NULL)
2729
0
      break;
2730
0
    event_strlist_append(dest_event, SETTINGS_EVENT_FILTER_NAME,
2731
0
             filter_name);
2732
0
  }
2733
0
}
2734
2735
static int
2736
settings_get_real(struct event *event,
2737
      const char *filter_key, const char *filter_value,
2738
      const struct setting_parser_info *info,
2739
      const struct settings_get_params *params,
2740
      const char *source_filename,
2741
      unsigned int source_linenum,
2742
      const void **set_r, const char **error_r)
2743
0
{
2744
0
  struct settings_root *scan_root, *root = NULL;
2745
0
  struct settings_mmap *mmap = NULL;
2746
0
  struct settings_instance *scan_instance, *instance = NULL;
2747
0
  struct event *lookup_event, *scan_event = event;
2748
0
  const char *filter_name = NULL;
2749
0
  bool filter_name_required = FALSE;
2750
2751
0
  lookup_event = event_create(event);
2752
0
  if (filter_value != NULL) {
2753
0
    filter_name = t_strdup_printf("%s/%s", filter_key,
2754
0
      settings_section_escape(filter_value));
2755
    /* the filter key=value field is needed by setting override
2756
       handling to incrementally generate the filter */
2757
0
    event_add_str(lookup_event, filter_key, filter_value);
2758
0
    event_strlist_append(lookup_event, SETTINGS_EVENT_FILTER_NAME,
2759
0
             filter_name);
2760
0
    filter_name_required = TRUE;
2761
0
  } else if (filter_key != NULL) {
2762
0
    filter_name = filter_key;
2763
0
    event_strlist_append(lookup_event, SETTINGS_EVENT_FILTER_NAME,
2764
0
             filter_name);
2765
0
    filter_name_required = TRUE;
2766
0
  }
2767
2768
0
  do {
2769
0
    scan_root = event_get_ptr(scan_event, SETTINGS_EVENT_ROOT);
2770
0
    scan_instance = event_get_ptr(scan_event,
2771
0
                SETTINGS_EVENT_INSTANCE);
2772
2773
0
    if (root == NULL)
2774
0
      root = scan_root;
2775
0
    else if ((scan_root != NULL && root != scan_root) ||
2776
0
       (scan_instance != NULL && root != scan_instance->root)) {
2777
      /* settings root changed - ignore the rest of the
2778
         event hierarchy. */
2779
0
      break;
2780
0
    }
2781
0
    if (instance == NULL && scan_instance != NULL) {
2782
0
      instance = scan_instance;
2783
0
      root = instance->root;
2784
0
    }
2785
2786
0
    settings_event_convert_filter_names(scan_event, lookup_event);
2787
0
    scan_event = event_get_parent(scan_event);
2788
0
  } while (scan_event != NULL);
2789
2790
0
  if (root == NULL)
2791
0
    i_panic("settings_get() - event has no SETTINGS_EVENT_ROOT");
2792
0
  if (instance != NULL)
2793
0
    mmap = instance->mmap;
2794
0
  else
2795
0
    mmap = root->mmap;
2796
2797
  /* no instance-specific settings */
2798
0
  struct settings_instance empty_instance = {
2799
0
    .mmap = mmap,
2800
0
  };
2801
0
  if (instance == NULL)
2802
0
    instance = &empty_instance;
2803
2804
0
  struct settings_apply_ctx ctx = {
2805
0
    .event = lookup_event,
2806
0
    .root = root,
2807
0
    .instance = instance,
2808
0
    .info = info,
2809
0
    .flags = params->flags,
2810
0
    .escape_func = params->escape_func,
2811
0
    .escape_context = params->escape_context,
2812
0
    .filter_name = filter_name,
2813
0
    .filter_key = filter_key,
2814
0
    .filter_value = filter_value,
2815
0
    .filter_name_required = filter_name_required,
2816
0
  };
2817
2818
0
  int ret = settings_instance_get(&ctx, source_filename, source_linenum,
2819
0
          set_r, error_r);
2820
0
  if (ret < 0) {
2821
0
    *error_r = t_strdup_printf("%s settings%s: %s", info->name,
2822
0
      filter_name == NULL ? "" :
2823
0
      t_strdup_printf(" (filter=%s)", filter_name),
2824
0
      *error_r);
2825
0
  }
2826
0
  settings_parser_unref(&ctx.parser);
2827
0
  event_unref(&lookup_event);
2828
0
  array_free(&ctx.set_seen);
2829
0
  str_free(&ctx.str);
2830
0
  pool_unref(&ctx.temp_pool);
2831
0
  return ret;
2832
0
}
2833
2834
bool settings_key_exists(struct event *event, const char *key)
2835
0
{
2836
0
  struct settings_root *root = NULL;
2837
0
  do {
2838
0
    root = event_get_ptr(event, SETTINGS_EVENT_ROOT);
2839
0
    event = event_get_parent(event);
2840
0
  } while (root == NULL && event != NULL);
2841
0
  if (root == NULL)
2842
0
    i_panic("settings_key_exists() - event has no SETTINGS_EVENT_ROOT");
2843
2844
0
  bool ret;
2845
0
  T_BEGIN {
2846
0
    size_t len = strlen(key);
2847
0
    if (len > 0 && key[len-1] == SETTINGS_APPEND_KEY_SUFFIX[0])
2848
0
      key = t_strndup(key, len - 1);
2849
2850
0
    enum setting_type set_type ATTR_UNUSED;
2851
0
    const void *blocks ATTR_UNUSED;
2852
0
    ret = settings_mmap_lookup_key(root->mmap, key,
2853
0
                 &set_type, &blocks);
2854
0
  } T_END;
2855
0
  return ret;
2856
0
}
2857
2858
struct settings_filter_array_item {
2859
  union {
2860
    unsigned int uint;
2861
    const char *str;
2862
  } order;
2863
  const char *value;
2864
};
2865
2866
static int
2867
settings_filter_array_uint_cmp(const struct settings_filter_array_item *item1,
2868
             const struct settings_filter_array_item *item2)
2869
0
{
2870
0
  if (item1->order.uint < item2->order.uint)
2871
0
    return -1;
2872
0
  if (item1->order.uint > item2->order.uint)
2873
0
    return 1;
2874
0
  return 0;
2875
0
}
2876
2877
static int
2878
settings_filter_array_str_cmp(const struct settings_filter_array_item *item1,
2879
            const struct settings_filter_array_item *item2)
2880
0
{
2881
0
  return strcmp(item1->order.str, item2->order.str);
2882
0
}
2883
2884
static int
2885
settings_sort_filter_array(struct event *event, const char *field_name,
2886
         const struct setting_filter_array_order *order,
2887
         ARRAY_TYPE(const_string) *fvals_arr,
2888
         const struct settings_get_params *params,
2889
         const char *source_filename,
2890
         unsigned int source_linenum, const char **error_r)
2891
0
{
2892
0
  const char **fvals;
2893
0
  unsigned int fidx, count, i;
2894
2895
0
  if (!array_is_created(fvals_arr))
2896
0
    return 0;
2897
2898
  /* Find definition index of order field */
2899
0
  if (!setting_parser_info_find_key(order->info, order->field_name,
2900
0
            &fidx))
2901
0
    i_panic("BUG: Order field %s for filter array %s in %s "
2902
0
      "not found",
2903
0
      order->field_name, field_name, order->info->name);
2904
2905
  /* Resolve alias */
2906
0
  while (fidx > 0 && order->info->defines[fidx].type == SET_ALIAS)
2907
0
    fidx--;
2908
2909
  /* Determine type of field */
2910
0
  enum {
2911
0
    _ITEM_TYPE_UINT,
2912
0
    _ITEM_TYPE_STR,
2913
0
  } item_type;
2914
2915
0
  const struct setting_define *order_def = &order->info->defines[fidx];
2916
0
  switch (order_def->type) {
2917
0
  case SET_UINT:
2918
0
  case SET_UINT_OCT:
2919
0
  case SET_TIME:
2920
0
  case SET_TIME_MSECS:
2921
0
    item_type = _ITEM_TYPE_UINT;
2922
0
    break;
2923
0
  case SET_STR:
2924
0
  case SET_STR_NOVARS:
2925
0
  case SET_PATH_FILE:
2926
0
  case SET_PATH_DIR:
2927
0
    item_type = _ITEM_TYPE_STR;
2928
0
    break;
2929
0
  case SET_ALIAS:
2930
0
    i_panic("BUG: Order field %s for filter array %s in %s "
2931
0
      "is an invalid alias",
2932
0
      order->field_name, field_name, order->info->name);
2933
0
  default:
2934
0
    i_panic("BUG: Order field %s for filter array %s in %s "
2935
0
      "has a type unsuitable for defining an order",
2936
0
      order->field_name, field_name, order->info->name);
2937
0
  }
2938
2939
  /* Read all order fields from filter array items */
2940
0
  ARRAY(struct settings_filter_array_item) items_arr;
2941
2942
0
  fvals = array_get_modifiable(fvals_arr, &count);
2943
0
  t_array_init(&items_arr, count);
2944
0
  for (i = 0; i < count; i++) {
2945
0
    const void *set;
2946
0
    int ret;
2947
2948
0
    T_BEGIN {
2949
0
      ret = settings_get_real(event, field_name, fvals[i],
2950
0
            order->info, params,
2951
0
            source_filename, source_linenum,
2952
0
            &set, error_r);
2953
0
    } T_END_PASS_STR_IF(ret < 0, error_r);
2954
0
    if (ret < 0)
2955
0
      return -1;
2956
0
    if (ret == 0) {
2957
0
      *error_r = t_strdup_printf(
2958
0
        "Filter %s=%s unexpectedly not found while sorting "
2959
0
        "(invalid userdb or -o override settings?)",
2960
0
        field_name, fvals[i]);
2961
0
      return -1;
2962
0
    }
2963
2964
0
    pool_t *pool_p = PTR_OFFSET(set, order->info->pool_offset1 - 1);
2965
0
    pool_t pool = *pool_p;
2966
0
    struct settings_filter_array_item *item;
2967
2968
0
    item = array_append_space(&items_arr);
2969
0
    item->value = fvals[i];
2970
2971
0
    switch (item_type) {
2972
0
    case _ITEM_TYPE_UINT:
2973
0
      item->order.uint = *((unsigned int *)
2974
0
        PTR_OFFSET(set, order_def->offset));
2975
0
      break;
2976
0
    case _ITEM_TYPE_STR:
2977
0
      item->order.str = *((const char **)
2978
0
        PTR_OFFSET(set, order_def->offset));
2979
0
      item->order.str = t_strdup(item->order.str);
2980
0
      break;
2981
0
    default:
2982
0
      i_unreached();
2983
0
    }
2984
2985
0
    pool_unref(&pool);
2986
0
  }
2987
2988
  /* Sort the filter array items based on order field */
2989
0
  switch (item_type) {
2990
0
  case _ITEM_TYPE_UINT:
2991
0
    array_sort(&items_arr, settings_filter_array_uint_cmp);
2992
0
    break;
2993
0
  case _ITEM_TYPE_STR:
2994
0
    array_sort(&items_arr, settings_filter_array_str_cmp);
2995
0
    break;
2996
0
  default:
2997
0
    i_unreached();
2998
0
  }
2999
3000
  /* Move the items in the settings */
3001
0
  const struct settings_filter_array_item *items;
3002
0
  unsigned int items_count;
3003
3004
0
  items = array_get(&items_arr, &items_count);
3005
0
  i_assert(items_count == count);
3006
0
  for (i = 0; i < count; i++) {
3007
0
    if (!order->reverse)
3008
0
      fvals[i] = items[i].value;
3009
0
    else
3010
0
      fvals[i] = items[count - 1 - i].value;
3011
0
  }
3012
0
  return 0;
3013
0
}
3014
3015
static int
3016
settings_get_full(struct event *event,
3017
      const char *filter_key, const char *filter_value,
3018
      const struct setting_parser_info *info,
3019
      const struct settings_get_params *params,
3020
      const char *source_filename,
3021
      unsigned int source_linenum,
3022
      const void **set_r, const char **error_r)
3023
0
{
3024
0
  const void *set;
3025
0
  int ret;
3026
3027
0
  *set_r = NULL;
3028
0
  T_BEGIN {
3029
0
    ret = settings_get_real(event, filter_key, filter_value, info,
3030
0
          params, source_filename, source_linenum,
3031
0
          &set, error_r);
3032
0
  } T_END_PASS_STR_IF(ret < 0, error_r);
3033
0
  if (ret <= 0)
3034
0
    return ret;
3035
0
  if ((params->flags & SETTINGS_GET_FLAG_SORT_FILTER_ARRAYS) == 0) {
3036
    /* Sorting filter arrays disabled */
3037
0
    *set_r = set;
3038
0
    return 1;
3039
0
  }
3040
3041
0
  const struct setting_define *def;
3042
3043
  /* Sort filter arrays when order is defined */
3044
0
  for (def = info->defines; def->key != NULL; def++) {
3045
0
    int ret;
3046
3047
0
    if (def->type != SET_FILTER_ARRAY) {
3048
      /* Not a filter array */
3049
0
      continue;
3050
0
    }
3051
0
    if (def->filter_array_order == NULL) {
3052
      /* No order defined */
3053
0
      continue;
3054
0
    }
3055
3056
0
    ARRAY_TYPE(const_string) *fvals_arr =
3057
0
      PTR_OFFSET(set, def->offset);
3058
0
    i_assert(fvals_arr != NULL);
3059
3060
    /* Sort this array */
3061
0
    T_BEGIN {
3062
0
      ret = settings_sort_filter_array(
3063
0
        event, def->key, def->filter_array_order,
3064
0
        fvals_arr, params,
3065
0
        source_filename, source_linenum, error_r);
3066
0
    } T_END_PASS_STR_IF(ret < 0, error_r);
3067
0
    if (ret < 0) {
3068
0
      pool_t *pool_p = PTR_OFFSET(set, info->pool_offset1 - 1);
3069
0
      pool_t pool = *pool_p;
3070
0
      pool_unref(&pool);
3071
0
      return -1;
3072
0
    }
3073
0
  }
3074
3075
0
  *set_r = set;
3076
0
  return 1;
3077
0
}
3078
3079
#undef settings_get
3080
int settings_get(struct event *event,
3081
     const struct setting_parser_info *info,
3082
     enum settings_get_flags flags,
3083
     const char *source_filename,
3084
     unsigned int source_linenum,
3085
     const void **set_r, const char **error_r)
3086
0
{
3087
0
  const struct settings_get_params params = {
3088
0
    .flags = flags,
3089
0
  };
3090
0
  int ret = settings_get_full(event, NULL, NULL, info, &params,
3091
0
            source_filename, source_linenum,
3092
0
            set_r, error_r);
3093
0
  i_assert(ret != 0);
3094
0
  return ret < 0 ? -1 : 0;
3095
0
}
3096
3097
#undef settings_get_params
3098
int settings_get_params(struct event *event,
3099
      const struct setting_parser_info *info,
3100
      const struct settings_get_params *params,
3101
      const char *source_filename,
3102
      unsigned int source_linenum,
3103
      const void **set_r, const char **error_r)
3104
0
{
3105
0
  int ret = settings_get_full(event, NULL, NULL, info, params,
3106
0
            source_filename, source_linenum,
3107
0
            set_r, error_r);
3108
0
  i_assert(ret != 0);
3109
0
  return ret < 0 ? -1 : 0;
3110
0
}
3111
3112
#undef settings_get_filter
3113
int settings_get_filter(struct event *event,
3114
      const char *filter_key, const char *filter_value,
3115
      const struct setting_parser_info *info,
3116
      enum settings_get_flags flags,
3117
      const char *source_filename,
3118
      unsigned int source_linenum,
3119
      const void **set_r, const char **error_r)
3120
0
{
3121
0
  i_assert(filter_key != NULL);
3122
0
  i_assert(filter_value != NULL);
3123
3124
0
  const struct settings_get_params params = {
3125
0
    .flags = flags,
3126
0
  };
3127
0
  int ret = settings_get_full(event, filter_key, filter_value, info,
3128
0
            &params, source_filename, source_linenum,
3129
0
            set_r, error_r);
3130
0
  if (ret < 0)
3131
0
    return -1;
3132
0
  if (ret == 0) {
3133
    /* e.g. namespace=foo was given but no namespace/foo/name */
3134
0
    *error_r = t_strdup_printf(
3135
0
      "Filter %s=%s unexpectedly not found "
3136
0
      "(invalid userdb or -o override settings?)",
3137
0
      filter_key, filter_value);
3138
0
    return -1;
3139
0
  }
3140
0
  return 0;
3141
0
}
3142
3143
#undef settings_try_get_filter
3144
int settings_try_get_filter(struct event *event,
3145
          const char *filter_key, const char *filter_value,
3146
          const struct setting_parser_info *info,
3147
          enum settings_get_flags flags,
3148
          const char *source_filename,
3149
          unsigned int source_linenum,
3150
          const void **set_r, const char **error_r)
3151
0
{
3152
0
  i_assert(filter_key != NULL);
3153
0
  i_assert(filter_value != NULL);
3154
3155
0
  const struct settings_get_params params = {
3156
0
    .flags = flags,
3157
0
  };
3158
0
  return settings_get_full(event, filter_key, filter_value, info,
3159
0
         &params, source_filename, source_linenum,
3160
0
         set_r, error_r);
3161
0
}
3162
3163
#undef settings_get_or_fatal
3164
const void *
3165
settings_get_or_fatal(struct event *event,
3166
          const struct setting_parser_info *info,
3167
          const char *source_filename,
3168
          unsigned int source_linenum)
3169
0
{
3170
0
  const void *set;
3171
0
  const char *error;
3172
3173
0
  if (settings_get(event, info, 0, source_filename,
3174
0
       source_linenum, &set, &error) < 0)
3175
0
    i_fatal("%s", error);
3176
0
  return set;
3177
0
}
3178
3179
static void
3180
settings_override_fill(struct settings_override *set, pool_t pool,
3181
           const char *key, const char *value,
3182
           enum settings_override_type type)
3183
0
{
3184
0
  set->pool = pool;
3185
0
  set->type = type;
3186
0
  size_t len = strlen(key);
3187
0
  T_BEGIN {
3188
0
    if (len > 0 && key[len-1] == SETTINGS_APPEND_KEY_SUFFIX[0]) {
3189
      /* key+=value */
3190
0
      set->append = TRUE;
3191
0
      len--;
3192
0
      while (len > 0 && i_isspace(key[len-1]))
3193
0
        len--;
3194
0
      key = t_strndup(key, len);
3195
0
    }
3196
0
    set->key = set->orig_key = p_strdup(pool, key);
3197
0
    set->value = p_strdup(pool, value);
3198
0
  } T_END;
3199
0
}
3200
3201
void settings_override(struct settings_instance *instance,
3202
           const char *key, const char *value,
3203
           enum settings_override_type type)
3204
0
{
3205
0
  if (!array_is_created(&instance->overrides))
3206
0
    p_array_init(&instance->overrides, instance->pool, 16);
3207
0
  struct settings_override *set =
3208
0
    array_append_space(&instance->overrides);
3209
0
  set->overrides_array = &instance->overrides;
3210
0
  settings_override_fill(set, instance->pool, key, value, type);
3211
0
}
3212
3213
void settings_root_override(struct settings_root *root,
3214
          const char *key, const char *value,
3215
          enum settings_override_type type)
3216
0
{
3217
0
  if (!array_is_created(&root->overrides))
3218
0
    p_array_init(&root->overrides, root->pool, 16);
3219
0
  struct settings_override *set =
3220
0
    array_append_space(&root->overrides);
3221
0
  set->overrides_array = &root->overrides;
3222
0
  settings_override_fill(set, root->pool, key, value, type);
3223
0
}
3224
3225
static bool
3226
settings_override_equals(struct settings_override *set, const char *key,
3227
       enum settings_override_type type)
3228
0
{
3229
0
  size_t key_len = strlen(key);
3230
0
  bool key_append = (key_len > 0 &&
3231
0
         key[key_len-1] == SETTINGS_APPEND_KEY_SUFFIX[0]);
3232
3233
0
  if (set->type != type)
3234
0
    return FALSE;
3235
0
  if (set->append != key_append)
3236
0
    return FALSE;
3237
3238
0
  if (key_append) {
3239
0
    size_t set_len = strlen(set->key);
3240
3241
0
    if (set_len != key_len - 1)
3242
0
      return FALSE;
3243
0
    return (strncmp(key, set->key, key_len - 1) == 0);
3244
0
  }
3245
0
  return (strcmp(key, set->key) == 0);
3246
0
}
3247
3248
bool settings_root_override_remove(struct settings_root *root,
3249
           const char *key,
3250
           enum settings_override_type type)
3251
0
{
3252
0
  if (!array_is_created(&root->overrides))
3253
0
    return FALSE;
3254
3255
0
  struct settings_override *set;
3256
3257
0
  array_foreach_modifiable(&root->overrides, set) {
3258
0
    if (!settings_override_equals(set, key, type))
3259
0
      continue;
3260
3261
0
    settings_override_free(set);
3262
0
    array_delete(&root->overrides,
3263
0
           array_foreach_idx(&root->overrides, set), 1);
3264
0
    return TRUE;
3265
0
  }
3266
3267
0
  return FALSE;
3268
0
}
3269
3270
static const char *settings_event_get_free_filter_name_key(struct event *event)
3271
0
{
3272
0
  if (event_get_ptr(event, SETTINGS_EVENT_FILTER_NAME) == NULL)
3273
0
    return SETTINGS_EVENT_FILTER_NAME;
3274
3275
0
  string_t *str = t_str_new(strlen(SETTINGS_EVENT_FILTER_NAME) + 1);
3276
0
  str_append(str, SETTINGS_EVENT_FILTER_NAME);
3277
0
  for (unsigned int i = 2;; i++) {
3278
0
    str_truncate(str, strlen(SETTINGS_EVENT_FILTER_NAME));
3279
0
    str_printfa(str, "%u", i);
3280
0
    if (event_get_ptr(event, str_c(str)) == NULL)
3281
0
      break;
3282
0
  }
3283
0
  return str_c(str);
3284
0
}
3285
3286
void settings_event_add_filter_name(struct event *event, const char *name)
3287
0
{
3288
0
  event_set_ptr(event, settings_event_get_free_filter_name_key(event),
3289
0
          p_strdup(event_get_pool(event), name));
3290
0
}
3291
3292
void settings_event_add_list_filter_name(struct event *event,
3293
           const char *key, const char *value)
3294
0
{
3295
0
  char *filter_name =
3296
0
    p_strconcat(event_get_pool(event),
3297
0
          key, "/", settings_section_escape(value), NULL);
3298
0
  event_set_ptr(event, settings_event_get_free_filter_name_key(event),
3299
0
          filter_name);
3300
0
}
3301
3302
static struct settings_instance *
3303
settings_instance_alloc(void)
3304
0
{
3305
0
  pool_t pool = pool_alloconly_create("settings instance", 1024);
3306
0
  struct settings_instance *instance =
3307
0
    p_new(pool, struct settings_instance, 1);
3308
0
  instance->pool = pool;
3309
0
  return instance;
3310
0
}
3311
3312
struct settings_instance *
3313
settings_instance_new(struct settings_root *root)
3314
0
{
3315
0
  struct settings_instance *instance = settings_instance_alloc();
3316
0
  instance->root = root;
3317
0
  instance->mmap = root->mmap;
3318
0
  return instance;
3319
0
}
3320
3321
struct settings_instance *
3322
settings_instance_dup(const struct settings_instance *src)
3323
0
{
3324
0
  struct settings_instance *dest = settings_instance_alloc();
3325
0
  dest->root = src->root;
3326
0
  dest->mmap = src->mmap;
3327
3328
0
  if (!array_is_created(&src->overrides))
3329
0
    return dest;
3330
3331
0
  p_array_init(&dest->overrides, dest->pool,
3332
0
         array_count(&src->overrides) + 8);
3333
0
  const struct settings_override *src_set;
3334
0
  array_foreach(&src->overrides, src_set) {
3335
0
    struct settings_override *dest_set =
3336
0
      array_append_space(&dest->overrides);
3337
    /* regenerate filter later */
3338
0
    dest_set->pool = dest->pool;
3339
0
    dest_set->type = src_set->type;
3340
0
    dest_set->append = src_set->append;
3341
0
    dest_set->orig_key = p_strdup(dest->pool, src_set->orig_key);
3342
0
    dest_set->key = dest_set->orig_key;
3343
0
    dest_set->value = p_strdup(dest->pool, src_set->value);
3344
0
    dest_set->overrides_array = &dest->overrides;
3345
0
  }
3346
0
  return dest;
3347
0
}
3348
3349
void settings_instance_free(struct settings_instance **_instance)
3350
0
{
3351
0
  struct settings_instance *instance = *_instance;
3352
0
  struct settings_override *override;
3353
3354
0
  if (instance == NULL)
3355
0
    return;
3356
3357
0
  *_instance = NULL;
3358
3359
0
  if (array_is_created(&instance->overrides)) {
3360
0
    array_foreach_modifiable(&instance->overrides, override)
3361
0
      settings_override_free(override);
3362
0
  }
3363
0
  pool_unref(&instance->pool);
3364
0
}
3365
3366
struct settings_root *settings_root_init(void)
3367
0
{
3368
0
  pool_t pool = pool_alloconly_create("settings root", 128);
3369
0
  struct settings_root *root = p_new(pool, struct settings_root, 1);
3370
0
  root->pool = pool;
3371
0
  return root;
3372
0
}
3373
3374
void settings_root_deinit(struct settings_root **_root)
3375
0
{
3376
0
  struct settings_root *root = *_root;
3377
0
  struct settings_override *override;
3378
0
  struct settings_mmap_pool *mpool;
3379
3380
0
  if (root == NULL)
3381
0
    return;
3382
0
  *_root = NULL;
3383
3384
0
  if (array_is_created(&root->overrides)) {
3385
0
    array_foreach_modifiable(&root->overrides, override)
3386
0
      settings_override_free(override);
3387
0
  }
3388
0
  settings_mmap_unref(&root->mmap);
3389
3390
0
  for (mpool = root->settings_pools; mpool != NULL; mpool = mpool->next) {
3391
0
    i_warning("Leaked settings: %s:%u",
3392
0
        mpool->source_filename, mpool->source_linenum);
3393
0
  }
3394
0
  pool_unref(&root->pool);
3395
0
}
3396
3397
struct settings_root *settings_root_find(const struct event *event)
3398
0
{
3399
0
  struct settings_root *root;
3400
3401
0
  do {
3402
0
    root = event_get_ptr(event, SETTINGS_EVENT_ROOT);
3403
0
    if (root != NULL)
3404
0
      return root;
3405
0
    event = event_get_parent(event);
3406
0
  } while (event != NULL);
3407
0
  return NULL;
3408
0
}
3409
3410
static void set_registered_infos_free(void)
3411
0
{
3412
0
  array_free(&set_registered_infos);
3413
0
}
3414
3415
static int
3416
setting_parser_info_cmp(const struct setting_parser_info *info,
3417
      const struct setting_parser_info *const *info2)
3418
0
{
3419
0
  return *info2 == info ? 0 : -1;
3420
0
}
3421
3422
void settings_info_register(const struct setting_parser_info *info)
3423
0
{
3424
0
  if (!array_is_created(&set_registered_infos)) {
3425
0
    i_array_init(&set_registered_infos, 16);
3426
0
    lib_atexit(set_registered_infos_free);
3427
0
  }
3428
0
  if (array_lsearch(&set_registered_infos, info,
3429
0
        setting_parser_info_cmp) == NULL)
3430
0
    array_push_back(&set_registered_infos, &info);
3431
0
}
3432
3433
struct settings_instance *settings_instance_find(const struct event *event)
3434
0
{
3435
0
  struct settings_instance *instance;
3436
3437
0
  do {
3438
0
    instance = event_get_ptr(event, SETTINGS_EVENT_INSTANCE);
3439
0
    if (instance != NULL)
3440
0
      return instance;
3441
0
    event = event_get_parent(event);
3442
0
  } while (event != NULL);
3443
0
  return NULL;
3444
0
}
3445
3446
void settings_simple_init(struct settings_simple *set_r,
3447
        const char *const settings[])
3448
0
{
3449
0
  i_zero(set_r);
3450
0
  set_r->root = settings_root_init();
3451
0
  set_r->event = event_create(NULL);
3452
0
  event_set_ptr(set_r->event, SETTINGS_EVENT_ROOT, set_r->root);
3453
0
  if (settings != NULL)
3454
0
    settings_simple_update(set_r, settings);
3455
0
}
3456
3457
void settings_simple_deinit(struct settings_simple *set)
3458
0
{
3459
0
  settings_instance_free(&set->instance);
3460
0
  settings_root_deinit(&set->root);
3461
0
  event_unref(&set->event);
3462
0
}
3463
3464
void settings_simple_update(struct settings_simple *set,
3465
          const char *const settings[])
3466
0
{
3467
0
  settings_instance_free(&set->instance);
3468
0
  set->instance = settings_instance_new(set->root);
3469
0
  for (unsigned int i = 0; settings[i] != NULL; i += 2) {
3470
0
    settings_override(set->instance, settings[i], settings[i + 1],
3471
0
          SETTINGS_OVERRIDE_TYPE_CODE);
3472
0
  }
3473
0
  event_set_ptr(set->event, SETTINGS_EVENT_INSTANCE, set->instance);
3474
0
}