1 /* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "array.h"
5 #include "hash-format.h"
6 #include "var-expand.h"
7 #include "unichar.h"
8 #include "hostpid.h"
9 #include "settings-parser.h"
10 #include "message-address.h"
11 #include "message-header-parser.h"
12 #include "smtp-address.h"
13 #include "mail-index.h"
14 #include "mail-user.h"
15 #include "mail-namespace.h"
16 #include "mail-storage-private.h"
17 #include "mail-storage-settings.h"
18 #include "iostream-ssl.h"
19
20 #include <stddef.h>
21
22 static bool mail_storage_settings_check(void *_set, pool_t pool, const char **error_r);
23 static bool namespace_settings_check(void *_set, pool_t pool, const char **error_r);
24 static bool mailbox_settings_check(void *_set, pool_t pool, const char **error_r);
25 static bool mail_user_settings_check(void *_set, pool_t pool, const char **error_r);
26 static bool mail_user_settings_expand_check(void *_set, pool_t pool ATTR_UNUSED, const char **error_r);
27
28 #undef DEF
29 #define DEF(type, name) \
30 SETTING_DEFINE_STRUCT_##type(#name, name, struct mail_storage_settings)
31
32 static const struct setting_define mail_storage_setting_defines[] = {
33 DEF(STR_VARS, mail_location),
34 { .type = SET_ALIAS, .key = "mail" },
35 DEF(STR_VARS, mail_attachment_fs),
36 DEF(STR_VARS, mail_attachment_dir),
37 DEF(STR, mail_attachment_hash),
38 DEF(SIZE, mail_attachment_min_size),
39 DEF(STR, mail_attachment_detection_options),
40 DEF(STR_VARS, mail_attribute_dict),
41 DEF(UINT, mail_prefetch_count),
42 DEF(STR, mail_cache_fields),
43 DEF(STR, mail_always_cache_fields),
44 DEF(STR, mail_never_cache_fields),
45 DEF(STR, mail_server_comment),
46 DEF(STR, mail_server_admin),
47 DEF(UINT, mail_cache_min_mail_count),
48 DEF(TIME_HIDDEN, mail_cache_unaccessed_field_drop),
49 DEF(SIZE_HIDDEN, mail_cache_record_max_size),
50 DEF(SIZE_HIDDEN, mail_cache_max_size),
51 DEF(SIZE_HIDDEN, mail_cache_purge_min_size),
52 DEF(UINT_HIDDEN, mail_cache_purge_delete_percentage),
53 DEF(UINT_HIDDEN, mail_cache_purge_continued_percentage),
54 DEF(UINT_HIDDEN, mail_cache_purge_header_continue_count),
55 DEF(SIZE_HIDDEN, mail_index_rewrite_min_log_bytes),
56 DEF(SIZE_HIDDEN, mail_index_rewrite_max_log_bytes),
57 DEF(SIZE_HIDDEN, mail_index_log_rotate_min_size),
58 DEF(SIZE_HIDDEN, mail_index_log_rotate_max_size),
59 DEF(TIME_HIDDEN, mail_index_log_rotate_min_age),
60 DEF(TIME_HIDDEN, mail_index_log2_max_age),
61 DEF(TIME, mailbox_idle_check_interval),
62 DEF(UINT, mail_max_keyword_length),
63 DEF(TIME, mail_max_lock_timeout),
64 DEF(TIME, mail_temp_scan_interval),
65 DEF(UINT, mail_vsize_bg_after_count),
66 DEF(UINT, mail_sort_max_read_count),
67 DEF(BOOL, mail_save_crlf),
68 DEF(ENUM, mail_fsync),
69 DEF(BOOL, mmap_disable),
70 DEF(BOOL, dotlock_use_excl),
71 DEF(BOOL, mail_nfs_storage),
72 DEF(BOOL, mail_nfs_index),
73 DEF(BOOL, mailbox_list_index),
74 DEF(BOOL, mailbox_list_index_very_dirty_syncs),
75 DEF(BOOL, mailbox_list_index_include_inbox),
76 DEF(BOOL, mail_debug),
77 DEF(BOOL, mail_full_filesystem_access),
78 DEF(BOOL, maildir_stat_dirs),
79 DEF(BOOL, mail_shared_explicit_inbox),
80 DEF(ENUM, lock_method),
81 DEF(STR, pop3_uidl_format),
82
83 DEF(STR, hostname),
84 DEF(STR, recipient_delimiter),
85
86 SETTING_DEFINE_LIST_END
87 };
88
89 const struct mail_storage_settings mail_storage_default_settings = {
90 .mail_location = "",
91 .mail_attachment_fs = "sis posix",
92 .mail_attachment_dir = "",
93 .mail_attachment_hash = "%{sha1}",
94 .mail_attachment_min_size = 1024*128,
95 .mail_attachment_detection_options = "",
96 .mail_attribute_dict = "",
97 .mail_prefetch_count = 0,
98 .mail_cache_fields = "flags",
99 .mail_always_cache_fields = "",
100 .mail_never_cache_fields = "imap.envelope",
101 .mail_server_comment = "",
102 .mail_server_admin = "",
103 .mail_cache_min_mail_count = 0,
104 .mail_cache_unaccessed_field_drop = 60*60*24*30,
105 .mail_cache_record_max_size = 64 * 1024,
106 .mail_cache_max_size = 1024 * 1024 * 1024,
107 .mail_cache_purge_min_size = 32 * 1024,
108 .mail_cache_purge_delete_percentage = 20,
109 .mail_cache_purge_continued_percentage = 200,
110 .mail_cache_purge_header_continue_count = 4,
111 .mail_index_rewrite_min_log_bytes = 8 * 1024,
112 .mail_index_rewrite_max_log_bytes = 128 * 1024,
113 .mail_index_log_rotate_min_size = 32 * 1024,
114 .mail_index_log_rotate_max_size = 1024 * 1024,
115 .mail_index_log_rotate_min_age = 5 * 60,
116 .mail_index_log2_max_age = 3600 * 24 * 2,
117 .mailbox_idle_check_interval = 30,
118 .mail_max_keyword_length = 50,
119 .mail_max_lock_timeout = 0,
120 .mail_temp_scan_interval = 7*24*60*60,
121 .mail_vsize_bg_after_count = 0,
122 .mail_sort_max_read_count = 0,
123 .mail_save_crlf = FALSE,
124 .mail_fsync = "optimized:never:always",
125 .mmap_disable = FALSE,
126 .dotlock_use_excl = TRUE,
127 .mail_nfs_storage = FALSE,
128 .mail_nfs_index = FALSE,
129 .mailbox_list_index = TRUE,
130 .mailbox_list_index_very_dirty_syncs = FALSE,
131 .mailbox_list_index_include_inbox = FALSE,
132 .mail_debug = FALSE,
133 .mail_full_filesystem_access = FALSE,
134 .maildir_stat_dirs = FALSE,
135 .mail_shared_explicit_inbox = FALSE,
136 .lock_method = "fcntl:flock:dotlock",
137 .pop3_uidl_format = "%08Xu%08Xv",
138
139 .hostname = "",
140 .recipient_delimiter = "+",
141 };
142
143 const struct setting_parser_info mail_storage_setting_parser_info = {
144 .module_name = "mail",
145 .defines = mail_storage_setting_defines,
146 .defaults = &mail_storage_default_settings,
147
148 .type_offset = SIZE_MAX,
149 .struct_size = sizeof(struct mail_storage_settings),
150
151 .parent_offset = SIZE_MAX,
152 .parent = &mail_user_setting_parser_info,
153
154 .check_func = mail_storage_settings_check,
155 };
156
157 #undef DEF
158 #define DEF(type, name) \
159 SETTING_DEFINE_STRUCT_##type(#name, name, struct mailbox_settings)
160
161 static const struct setting_define mailbox_setting_defines[] = {
162 DEF(STR, name),
163 { .type = SET_ENUM, .key = "auto",
164 .offset = offsetof(struct mailbox_settings, autocreate) } ,
165 DEF(STR, special_use),
166 DEF(STR, driver),
167 DEF(STR, comment),
168 DEF(TIME, autoexpunge),
169 DEF(UINT, autoexpunge_max_mails),
170
171 SETTING_DEFINE_LIST_END
172 };
173
174 const struct mailbox_settings mailbox_default_settings = {
175 .name = "",
176 .autocreate = MAILBOX_SET_AUTO_NO":"
177 MAILBOX_SET_AUTO_CREATE":"
178 MAILBOX_SET_AUTO_SUBSCRIBE,
179 .special_use = "",
180 .driver = "",
181 .comment = "",
182 .autoexpunge = 0,
183 .autoexpunge_max_mails = 0
184 };
185
186 const struct setting_parser_info mailbox_setting_parser_info = {
187 .defines = mailbox_setting_defines,
188 .defaults = &mailbox_default_settings,
189
190 .type_offset = offsetof(struct mailbox_settings, name),
191 .struct_size = sizeof(struct mailbox_settings),
192
193 .parent_offset = SIZE_MAX,
194 .parent = &mail_user_setting_parser_info,
195
196 .check_func = mailbox_settings_check
197 };
198
199 #undef DEF
200 #undef DEFLIST_UNIQUE
201 #define DEF(type, name) \
202 SETTING_DEFINE_STRUCT_##type(#name, name, struct mail_namespace_settings)
203 #define DEFLIST_UNIQUE(field, name, defines) \
204 { .type = SET_DEFLIST_UNIQUE, .key = name, \
205 .offset = offsetof(struct mail_namespace_settings, field), \
206 .list_info = defines }
207
208 static const struct setting_define mail_namespace_setting_defines[] = {
209 DEF(STR, name),
210 DEF(ENUM, type),
211 DEF(STR, separator),
212 DEF(STR_VARS, prefix),
213 DEF(STR_VARS, location),
214 { .type = SET_ALIAS, .key = "mail" },
215 { .type = SET_ALIAS, .key = "mail_location" },
216 DEF(STR_VARS, alias_for),
217
218 DEF(BOOL, inbox),
219 DEF(BOOL, hidden),
220 DEF(ENUM, list),
221 DEF(BOOL, subscriptions),
222 DEF(BOOL, ignore_on_failure),
223 DEF(BOOL, disabled),
224 DEF(UINT, order),
225
226 DEFLIST_UNIQUE(mailboxes, "mailbox", &mailbox_setting_parser_info),
227
228 SETTING_DEFINE_LIST_END
229 };
230
231 const struct mail_namespace_settings mail_namespace_default_settings = {
232 .name = "",
233 .type = "private:shared:public",
234 .separator = "",
235 .prefix = "",
236 .location = "",
237 .alias_for = NULL,
238
239 .inbox = FALSE,
240 .hidden = FALSE,
241 .list = "yes:no:children",
242 .subscriptions = TRUE,
243 .ignore_on_failure = FALSE,
244 .disabled = FALSE,
245 .order = 0,
246
247 .mailboxes = ARRAY_INIT
248 };
249
250 const struct setting_parser_info mail_namespace_setting_parser_info = {
251 .defines = mail_namespace_setting_defines,
252 .defaults = &mail_namespace_default_settings,
253
254 .type_offset = offsetof(struct mail_namespace_settings, name),
255 .struct_size = sizeof(struct mail_namespace_settings),
256
257 .parent_offset = offsetof(struct mail_namespace_settings, user_set),
258 .parent = &mail_user_setting_parser_info,
259
260 .check_func = namespace_settings_check
261 };
262
263 #undef DEF
264 #undef DEFLIST_UNIQUE
265 #define DEF(type, name) \
266 SETTING_DEFINE_STRUCT_##type(#name, name, struct mail_user_settings)
267 #define DEFLIST_UNIQUE(field, name, defines) \
268 { .type = SET_DEFLIST_UNIQUE, .key = name, \
269 .offset = offsetof(struct mail_user_settings, field), \
270 .list_info = defines }
271
272 static const struct setting_define mail_user_setting_defines[] = {
273 DEF(STR, base_dir),
274 DEF(STR, auth_socket_path),
275 DEF(STR_VARS, mail_temp_dir),
276
277 DEF(STR, mail_uid),
278 DEF(STR, mail_gid),
279 DEF(STR_VARS, mail_home),
280 DEF(STR_VARS, mail_chroot),
281 DEF(STR, mail_access_groups),
282 DEF(STR, mail_privileged_group),
283 DEF(STR, valid_chroot_dirs),
284
285 DEF(UINT, first_valid_uid),
286 DEF(UINT, last_valid_uid),
287 DEF(UINT, first_valid_gid),
288 DEF(UINT, last_valid_gid),
289
290 DEF(STR, mail_plugins),
291 DEF(STR, mail_plugin_dir),
292
293 DEF(STR, mail_log_prefix),
294
295 DEF(STR, hostname),
296 DEF(STR_VARS, postmaster_address),
297
298 DEFLIST_UNIQUE(namespaces, "namespace", &mail_namespace_setting_parser_info),
299 { .type = SET_STRLIST, .key = "plugin",
300 .offset = offsetof(struct mail_user_settings, plugin_envs) },
301
302 SETTING_DEFINE_LIST_END
303 };
304
305 static const struct mail_user_settings mail_user_default_settings = {
306 .base_dir = PKG_RUNDIR,
307 .auth_socket_path = "auth-userdb",
308 .mail_temp_dir = "/tmp",
309
310 .mail_uid = "",
311 .mail_gid = "",
312 .mail_home = "",
313 .mail_chroot = "",
314 .mail_access_groups = "",
315 .mail_privileged_group = "",
316 .valid_chroot_dirs = "",
317
318 .first_valid_uid = 500,
319 .last_valid_uid = 0,
320 .first_valid_gid = 1,
321 .last_valid_gid = 0,
322
323 .mail_plugins = "",
324 .mail_plugin_dir = MODULEDIR,
325
326 .mail_log_prefix = "%s(%u)<%{pid}><%{session}>: ",
327
328 .hostname = "",
329 .postmaster_address = "postmaster@%{if;%d;ne;;%d;%{hostname}}",
330
331 .namespaces = ARRAY_INIT,
332 .plugin_envs = ARRAY_INIT
333 };
334
335 const struct setting_parser_info mail_user_setting_parser_info = {
336 .module_name = "mail",
337 .defines = mail_user_setting_defines,
338 .defaults = &mail_user_default_settings,
339
340 .type_offset = SIZE_MAX,
341 .struct_size = sizeof(struct mail_user_settings),
342
343 .parent_offset = SIZE_MAX,
344
345 .check_func = mail_user_settings_check,
346 #ifndef CONFIG_BINARY
347 .expand_check_func = mail_user_settings_expand_check,
348 #endif
349 };
350
351 const void *
mail_user_set_get_driver_settings(const struct setting_parser_info * info,const struct mail_user_settings * set,const char * driver)352 mail_user_set_get_driver_settings(const struct setting_parser_info *info,
353 const struct mail_user_settings *set,
354 const char *driver)
355 {
356 const void *dset;
357
358 dset = settings_find_dynamic(info, set, driver);
359 if (dset == NULL) {
360 i_panic("Default settings not found for storage driver %s",
361 driver);
362 }
363 return dset;
364 }
365
366 const struct mail_storage_settings *
mail_user_set_get_storage_set(struct mail_user * user)367 mail_user_set_get_storage_set(struct mail_user *user)
368 {
369 return mail_user_set_get_driver_settings(user->set_info, user->set,
370 MAIL_STORAGE_SET_DRIVER_NAME);
371 }
372
mail_namespace_get_driver_settings(struct mail_namespace * ns,struct mail_storage * storage)373 const void *mail_namespace_get_driver_settings(struct mail_namespace *ns,
374 struct mail_storage *storage)
375 {
376 return mail_user_set_get_driver_settings(storage->user->set_info,
377 ns->user_set, storage->name);
378 }
379
380 const struct dynamic_settings_parser *
mail_storage_get_dynamic_parsers(pool_t pool)381 mail_storage_get_dynamic_parsers(pool_t pool)
382 {
383 struct dynamic_settings_parser *parsers;
384 struct mail_storage *const *storages;
385 unsigned int i, j, count;
386
387 storages = array_get(&mail_storage_classes, &count);
388 parsers = p_new(pool, struct dynamic_settings_parser, 1 + count + 1);
389 parsers[0].name = MAIL_STORAGE_SET_DRIVER_NAME;
390 parsers[0].info = &mail_storage_setting_parser_info;
391
392 for (i = 0, j = 1; i < count; i++) {
393 if (storages[i]->v.get_setting_parser_info == NULL)
394 continue;
395
396 parsers[j].name = storages[i]->name;
397 parsers[j].info = storages[i]->v.get_setting_parser_info();
398 j++;
399 }
400 parsers[j].name = NULL;
401 return parsers;
402 }
403
404 static void
fix_base_path(struct mail_user_settings * set,pool_t pool,const char ** str)405 fix_base_path(struct mail_user_settings *set, pool_t pool, const char **str)
406 {
407 if (*str != NULL && **str != '\0' && **str != '/')
408 *str = p_strconcat(pool, set->base_dir, "/", *str, NULL);
409 }
410
411 /* <settings checks> */
mail_cache_fields_parse(const char * key,const char * value,const char ** error_r)412 static bool mail_cache_fields_parse(const char *key, const char *value,
413 const char **error_r)
414 {
415 const char *const *arr;
416
417 for (arr = t_strsplit_spaces(value, " ,"); *arr != NULL; arr++) {
418 const char *name = *arr;
419
420 if (strncasecmp(name, "hdr.", 4) == 0 &&
421 !message_header_name_is_valid(name+4)) {
422 *error_r = t_strdup_printf(
423 "Invalid %s: %s is not a valid header name",
424 key, name);
425 return FALSE;
426 }
427 }
428 return TRUE;
429 }
430
mail_storage_settings_check(void * _set,pool_t pool,const char ** error_r)431 static bool mail_storage_settings_check(void *_set, pool_t pool,
432 const char **error_r)
433 {
434 struct mail_storage_settings *set = _set;
435 struct hash_format *format;
436 const char *p, *error;
437 bool uidl_format_ok;
438 char c;
439
440 if (set->mailbox_idle_check_interval == 0) {
441 *error_r = "mailbox_idle_check_interval must not be 0";
442 return FALSE;
443 }
444
445 if (strcmp(set->mail_fsync, "optimized") == 0)
446 set->parsed_fsync_mode = FSYNC_MODE_OPTIMIZED;
447 else if (strcmp(set->mail_fsync, "never") == 0)
448 set->parsed_fsync_mode = FSYNC_MODE_NEVER;
449 else if (strcmp(set->mail_fsync, "always") == 0)
450 set->parsed_fsync_mode = FSYNC_MODE_ALWAYS;
451 else {
452 *error_r = t_strdup_printf("Unknown mail_fsync: %s",
453 set->mail_fsync);
454 return FALSE;
455 }
456
457 if (set->mail_nfs_index && !set->mmap_disable) {
458 *error_r = "mail_nfs_index=yes requires mmap_disable=yes";
459 return FALSE;
460 }
461 if (set->mail_nfs_index &&
462 set->parsed_fsync_mode != FSYNC_MODE_ALWAYS) {
463 *error_r = "mail_nfs_index=yes requires mail_fsync=always";
464 return FALSE;
465 }
466
467 if (!file_lock_method_parse(set->lock_method,
468 &set->parsed_lock_method)) {
469 *error_r = t_strdup_printf("Unknown lock_method: %s",
470 set->lock_method);
471 return FALSE;
472 }
473
474 if (set->mail_cache_max_size > 1024 * 1024 * 1024) {
475 *error_r = "mail_cache_max_size can't be over 1 GB";
476 return FALSE;
477 }
478 if (set->mail_cache_purge_delete_percentage > 100) {
479 *error_r = "mail_cache_purge_delete_percentage can't be over 100";
480 return FALSE;
481 }
482
483 uidl_format_ok = FALSE;
484 for (p = set->pop3_uidl_format; *p != '\0'; p++) {
485 if (p[0] != '%' || p[1] == '\0')
486 continue;
487
488 c = var_get_key(++p);
489 switch (c) {
490 case 'v':
491 case 'u':
492 case 'm':
493 case 'f':
494 case 'g':
495 uidl_format_ok = TRUE;
496 break;
497 case '%':
498 break;
499 default:
500 *error_r = t_strdup_printf(
501 "Unknown pop3_uidl_format variable: %%%c", c);
502 return FALSE;
503 }
504 }
505 if (!uidl_format_ok) {
506 *error_r = "pop3_uidl_format setting doesn't contain any "
507 "%% variables.";
508 return FALSE;
509 }
510
511 if (strchr(set->mail_attachment_hash, '/') != NULL) {
512 *error_r = "mail_attachment_hash setting "
513 "must not contain '/' characters";
514 return FALSE;
515 }
516 if (hash_format_init(set->mail_attachment_hash, &format, &error) < 0) {
517 *error_r = t_strconcat("Invalid mail_attachment_hash setting: ",
518 error, NULL);
519 return FALSE;
520 }
521 if (strchr(set->mail_attachment_hash, '-') != NULL) {
522 *error_r = "mail_attachment_hash setting "
523 "must not contain '-' characters";
524 return FALSE;
525 }
526 hash_format_deinit_free(&format);
527
528 // FIXME: check set->mail_server_admin syntax (RFC 5464, Section 6.2.2)
529
530 #ifndef CONFIG_BINARY
531 if (*set->hostname == '\0')
532 set->hostname = p_strdup(pool, my_hostdomain());
533 #endif
534
535 /* parse mail_attachment_indicator_options */
536 if (*set->mail_attachment_detection_options != '\0') {
537 ARRAY_TYPE(const_string) content_types;
538 p_array_init(&content_types, pool, 2);
539
540 const char *const *options =
541 t_strsplit_spaces(set->mail_attachment_detection_options, " ");
542
543 while(*options != NULL) {
544 const char *opt = *options;
545
546 if (strcmp(opt, "add-flags") == 0 ||
547 strcmp(opt, "add-flags-on-save") == 0) {
548 set->parsed_mail_attachment_detection_add_flags = TRUE;
549 } else if (strcmp(opt, "no-flags-on-fetch") == 0) {
550 set->parsed_mail_attachment_detection_no_flags_on_fetch = TRUE;
551 } else if (strcmp(opt, "exclude-inlined") == 0) {
552 set->parsed_mail_attachment_exclude_inlined = TRUE;
553 } else if (str_begins(opt, "content-type=")) {
554 const char *value = p_strdup(pool, opt+13);
555 array_push_back(&content_types, &value);
556 } else {
557 *error_r = t_strdup_printf("mail_attachment_detection_options: "
558 "Unknown option: %s", opt);
559 return FALSE;
560 }
561 options++;
562 }
563
564 array_append_zero(&content_types);
565 set->parsed_mail_attachment_content_type_filter = array_front(&content_types);
566 }
567
568 if (!mail_cache_fields_parse("mail_cache_fields",
569 set->mail_cache_fields, error_r))
570 return FALSE;
571 if (!mail_cache_fields_parse("mail_always_cache_fields",
572 set->mail_always_cache_fields, error_r))
573 return FALSE;
574 if (!mail_cache_fields_parse("mail_never_cache_fields",
575 set->mail_never_cache_fields, error_r))
576 return FALSE;
577 return TRUE;
578 }
579
namespace_settings_check(void * _set,pool_t pool ATTR_UNUSED,const char ** error_r)580 static bool namespace_settings_check(void *_set, pool_t pool ATTR_UNUSED,
581 const char **error_r)
582 {
583 struct mail_namespace_settings *ns = _set;
584 struct mail_namespace_settings *const *namespaces;
585 const char *name;
586 unsigned int i, count;
587
588 name = ns->prefix != NULL ? ns->prefix : "";
589
590 if (ns->separator[0] != '\0' && ns->separator[1] != '\0') {
591 *error_r = t_strdup_printf("Namespace '%s': "
592 "Hierarchy separator must be only one character long",
593 name);
594 return FALSE;
595 }
596 if (!uni_utf8_str_is_valid(name)) {
597 *error_r = t_strdup_printf("Namespace prefix not valid UTF8: %s",
598 name);
599 return FALSE;
600 }
601
602 if (ns->alias_for != NULL && !ns->disabled) {
603 if (array_is_created(&ns->user_set->namespaces)) {
604 namespaces = array_get(&ns->user_set->namespaces,
605 &count);
606 } else {
607 namespaces = NULL;
608 count = 0;
609 }
610 for (i = 0; i < count; i++) {
611 if (strcmp(namespaces[i]->prefix, ns->alias_for) == 0)
612 break;
613 }
614 if (i == count) {
615 *error_r = t_strdup_printf(
616 "Namespace '%s': alias_for points to "
617 "unknown namespace: %s", name, ns->alias_for);
618 return FALSE;
619 }
620 if (namespaces[i]->alias_for != NULL) {
621 *error_r = t_strdup_printf(
622 "Namespace '%s': alias_for chaining isn't "
623 "allowed: %s -> %s", name, ns->alias_for,
624 namespaces[i]->alias_for);
625 return FALSE;
626 }
627 }
628 return TRUE;
629 }
630
mailbox_special_use_exists(const char * name)631 static bool mailbox_special_use_exists(const char *name)
632 {
633 if (name[0] != '\\')
634 return FALSE;
635 name++;
636
637 if (strcasecmp(name, "All") == 0)
638 return TRUE;
639 if (strcasecmp(name, "Archive") == 0)
640 return TRUE;
641 if (strcasecmp(name, "Drafts") == 0)
642 return TRUE;
643 if (strcasecmp(name, "Flagged") == 0)
644 return TRUE;
645 if (strcasecmp(name, "Important") == 0)
646 return TRUE;
647 if (strcasecmp(name, "Junk") == 0)
648 return TRUE;
649 if (strcasecmp(name, "Sent") == 0)
650 return TRUE;
651 if (strcasecmp(name, "Trash") == 0)
652 return TRUE;
653 return FALSE;
654 }
655
656 static bool
mailbox_special_use_check(struct mailbox_settings * set,pool_t pool,const char ** error_r)657 mailbox_special_use_check(struct mailbox_settings *set, pool_t pool,
658 const char **error_r)
659 {
660 const char *const *uses, *str;
661 unsigned int i;
662
663 uses = t_strsplit_spaces(set->special_use, " ");
664 for (i = 0; uses[i] != NULL; i++) {
665 if (!mailbox_special_use_exists(uses[i])) {
666 *error_r = t_strdup_printf(
667 "mailbox %s: unknown special_use: %s",
668 set->name, uses[i]);
669 return FALSE;
670 }
671 }
672 /* make sure there are no extra spaces */
673 str = t_strarray_join(uses, " ");
674 if (strcmp(str, set->special_use) != 0)
675 set->special_use = p_strdup(pool, str);
676 return TRUE;
677 }
678
mailbox_settings_check(void * _set,pool_t pool,const char ** error_r)679 static bool mailbox_settings_check(void *_set, pool_t pool,
680 const char **error_r)
681 {
682 struct mailbox_settings *set = _set;
683
684 if (!uni_utf8_str_is_valid(set->name)) {
685 *error_r = t_strdup_printf("mailbox %s: name isn't valid UTF-8",
686 set->name);
687 return FALSE;
688 }
689 if (*set->special_use != '\0') {
690 if (!mailbox_special_use_check(set, pool, error_r))
691 return FALSE;
692 }
693 return TRUE;
694 }
695
mail_user_settings_check(void * _set,pool_t pool ATTR_UNUSED,const char ** error_r ATTR_UNUSED)696 static bool mail_user_settings_check(void *_set, pool_t pool ATTR_UNUSED,
697 const char **error_r ATTR_UNUSED)
698 {
699 struct mail_user_settings *set = _set;
700
701 #ifndef CONFIG_BINARY
702 fix_base_path(set, pool, &set->auth_socket_path);
703
704 if (*set->hostname == '\0')
705 set->hostname = p_strdup(pool, my_hostdomain());
706 if (set->postmaster_address[0] == SETTING_STRVAR_UNEXPANDED[0] &&
707 set->postmaster_address[1] == '\0') {
708 /* check for valid looking fqdn in hostname */
709 if (strchr(set->hostname, '.') == NULL) {
710 *error_r = "postmaster_address setting not given";
711 return FALSE;
712 }
713 set->postmaster_address =
714 p_strconcat(pool, SETTING_STRVAR_UNEXPANDED,
715 "postmaster@", set->hostname, NULL);
716 }
717 #else
718 if (*set->mail_plugins != '\0' &&
719 access(set->mail_plugin_dir, R_OK | X_OK) < 0) {
720 *error_r = t_strdup_printf(
721 "mail_plugin_dir: access(%s) failed: %m",
722 set->mail_plugin_dir);
723 return FALSE;
724 }
725 #endif
726 return TRUE;
727 }
728
729 #ifndef CONFIG_BINARY
parse_postmaster_address(const char * address,pool_t pool,struct mail_user_settings * set,const char ** error_r)730 static bool parse_postmaster_address(const char *address, pool_t pool,
731 struct mail_user_settings *set,
732 const char **error_r) ATTR_NULL(3)
733 {
734 struct message_address *addr;
735 struct smtp_address *smtp_addr;
736
737 addr = message_address_parse(pool,
738 (const unsigned char *)address,
739 strlen(address), 2, 0);
740 if (addr == NULL || addr->domain == NULL || addr->invalid_syntax ||
741 smtp_address_create_from_msg(pool, addr, &smtp_addr) < 0) {
742 *error_r = t_strdup_printf(
743 "invalid address `%s' specified for the "
744 "postmaster_address setting", address);
745 return FALSE;
746 }
747 if (addr->next != NULL) {
748 *error_r = "more than one address specified for the "
749 "postmaster_address setting";
750 return FALSE;
751 }
752 if (addr->name == NULL || *addr->name == '\0')
753 addr->name = "Postmaster";
754 if (set != NULL) {
755 set->_parsed_postmaster_address = addr;
756 set->_parsed_postmaster_address_smtp = smtp_addr;
757 }
758 return TRUE;
759 }
760
761 static bool
mail_user_settings_expand_check(void * _set,pool_t pool,const char ** error_r ATTR_UNUSED)762 mail_user_settings_expand_check(void *_set, pool_t pool,
763 const char **error_r ATTR_UNUSED)
764 {
765 struct mail_user_settings *set = _set;
766 const char *error;
767
768 /* Parse if possible. Perform error handling later. */
769 (void)parse_postmaster_address(set->postmaster_address, pool,
770 set, &error);
771 return TRUE;
772 }
773 #endif
774
775 /* </settings checks> */
776
777 static void
get_postmaster_address_error(const struct mail_user_settings * set,const char ** error_r)778 get_postmaster_address_error(const struct mail_user_settings *set,
779 const char **error_r)
780 {
781 if (parse_postmaster_address(set->postmaster_address,
782 pool_datastack_create(), NULL, error_r))
783 i_panic("postmaster_address='%s' parsing succeeded unexpectedly after it had already failed",
784 set->postmaster_address);
785 }
786
mail_user_set_get_postmaster_address(const struct mail_user_settings * set,const struct message_address ** address_r,const char ** error_r)787 bool mail_user_set_get_postmaster_address(const struct mail_user_settings *set,
788 const struct message_address **address_r,
789 const char **error_r)
790 {
791 *address_r = set->_parsed_postmaster_address;
792 if (*address_r != NULL)
793 return TRUE;
794 /* parsing failed - do it again to get the error */
795 get_postmaster_address_error(set, error_r);
796 return FALSE;
797 }
798
mail_user_set_get_postmaster_smtp(const struct mail_user_settings * set,const struct smtp_address ** address_r,const char ** error_r)799 bool mail_user_set_get_postmaster_smtp(const struct mail_user_settings *set,
800 const struct smtp_address **address_r,
801 const char **error_r)
802 {
803 *address_r = set->_parsed_postmaster_address_smtp;
804 if (*address_r != NULL)
805 return TRUE;
806 /* parsing failed - do it again to get the error */
807 get_postmaster_address_error(set, error_r);
808 return FALSE;
809 }
810