1 /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "ioloop.h"
5 #include "array.h"
6 #include "llist.h"
7 #include "mail-storage.h"
8 #include "str.h"
9 #include "str-sanitize.h"
10 #include "sha1.h"
11 #include "unichar.h"
12 #include "hex-binary.h"
13 #include "fs-api.h"
14 #include "iostream-ssl.h"
15 #include "file-dotlock.h"
16 #include "file-create-locked.h"
17 #include "istream.h"
18 #include "eacces-error.h"
19 #include "mkdir-parents.h"
20 #include "time-util.h"
21 #include "var-expand.h"
22 #include "dsasl-client.h"
23 #include "imap-date.h"
24 #include "settings-parser.h"
25 #include "mail-index-private.h"
26 #include "mail-index-alloc-cache.h"
27 #include "mailbox-tree.h"
28 #include "mailbox-list-private.h"
29 #include "mail-storage-private.h"
30 #include "mail-storage-settings.h"
31 #include "mail-namespace.h"
32 #include "mail-search.h"
33 #include "mail-search-register.h"
34 #include "mail-search-mime-register.h"
35 #include "mailbox-search-result-private.h"
36 #include "mailbox-guid-cache.h"
37 #include "mail-cache.h"
38 
39 #include <ctype.h>
40 
41 #define MAILBOX_DELETE_RETRY_SECS 30
42 #define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 255
43 
44 extern struct mail_search_register *mail_search_register_imap;
45 extern struct mail_search_register *mail_search_register_human;
46 
47 struct event_category event_category_storage = {
48 	.name = "storage",
49 };
50 struct event_category event_category_mailbox = {
51 	.parent = &event_category_storage,
52 	.name = "mailbox",
53 };
54 struct event_category event_category_mail = {
55 	.parent = &event_category_mailbox,
56 	.name = "mail",
57 };
58 
59 struct mail_storage_module_register mail_storage_module_register = { 0 };
60 struct mail_module_register mail_module_register = { 0 };
61 
62 struct mail_storage_mail_index_module mail_storage_mail_index_module =
63 	MODULE_CONTEXT_INIT(&mail_index_module_register);
64 ARRAY_TYPE(mail_storage) mail_storage_classes;
65 
66 static int mail_storage_init_refcount = 0;
67 
mail_storage_init(void)68 void mail_storage_init(void)
69 {
70 	if (mail_storage_init_refcount++ > 0)
71 		return;
72 	dsasl_clients_init();
73 	mailbox_attributes_init();
74 	mailbox_lists_init();
75 	mail_storage_hooks_init();
76 	i_array_init(&mail_storage_classes, 8);
77 	mail_storage_register_all();
78 	mailbox_list_register_all();
79 }
80 
mail_storage_deinit(void)81 void mail_storage_deinit(void)
82 {
83 	i_assert(mail_storage_init_refcount > 0);
84 	if (--mail_storage_init_refcount > 0)
85 		return;
86 	if (mail_search_register_human != NULL)
87 		mail_search_register_deinit(&mail_search_register_human);
88 	if (mail_search_register_imap != NULL)
89 		mail_search_register_deinit(&mail_search_register_imap);
90 	mail_search_mime_register_deinit();
91 	if (array_is_created(&mail_storage_classes))
92 		array_free(&mail_storage_classes);
93 	mail_storage_hooks_deinit();
94 	mailbox_lists_deinit();
95 	mailbox_attributes_deinit();
96 	dsasl_clients_deinit();
97 }
98 
mail_storage_class_register(struct mail_storage * storage_class)99 void mail_storage_class_register(struct mail_storage *storage_class)
100 {
101 	i_assert(mail_storage_find_class(storage_class->name) == NULL);
102 
103 	/* append it after the list, so the autodetection order is correct */
104 	array_push_back(&mail_storage_classes, &storage_class);
105 }
106 
mail_storage_class_unregister(struct mail_storage * storage_class)107 void mail_storage_class_unregister(struct mail_storage *storage_class)
108 {
109 	struct mail_storage *const *classes;
110 	unsigned int i, count;
111 
112 	classes = array_get(&mail_storage_classes, &count);
113 	for (i = 0; i < count; i++) {
114 		if (classes[i] == storage_class) {
115 			array_delete(&mail_storage_classes, i, 1);
116 			break;
117 		}
118 	}
119 }
120 
mail_storage_find_class(const char * name)121 struct mail_storage *mail_storage_find_class(const char *name)
122 {
123 	struct mail_storage *const *classes;
124 	unsigned int i, count;
125 
126 	i_assert(name != NULL);
127 
128 	classes = array_get(&mail_storage_classes, &count);
129 	for (i = 0; i < count; i++) {
130 		if (strcasecmp(classes[i]->name, name) == 0)
131 			return classes[i];
132 	}
133 	return NULL;
134 }
135 
136 static struct mail_storage *
mail_storage_autodetect(const struct mail_namespace * ns,struct mailbox_list_settings * set)137 mail_storage_autodetect(const struct mail_namespace *ns,
138 			struct mailbox_list_settings *set)
139 {
140 	struct mail_storage *const *classes;
141 	unsigned int i, count;
142 
143 	classes = array_get(&mail_storage_classes, &count);
144 	for (i = 0; i < count; i++) {
145 		if (classes[i]->v.autodetect != NULL) {
146 			if (classes[i]->v.autodetect(ns, set))
147 				return classes[i];
148 		}
149 	}
150 	return NULL;
151 }
152 
153 static void
mail_storage_set_autodetection(const char ** data,const char ** driver)154 mail_storage_set_autodetection(const char **data, const char **driver)
155 {
156 	const char *p;
157 
158 	/* check if data is in driver:data format (eg. mbox:~/mail) */
159 	p = *data;
160 	while (i_isalnum(*p) || *p == '_') p++;
161 
162 	if (*p == ':' && p != *data) {
163 		/* no autodetection if the storage driver is given. */
164 		*driver = t_strdup_until(*data, p);
165 		*data = p + 1;
166 	}
167 }
168 
169 static struct mail_storage *
mail_storage_get_class(struct mail_namespace * ns,const char * driver,struct mailbox_list_settings * list_set,enum mail_storage_flags flags,const char ** error_r)170 mail_storage_get_class(struct mail_namespace *ns, const char *driver,
171 		       struct mailbox_list_settings *list_set,
172 		       enum mail_storage_flags flags, const char **error_r)
173 {
174 	struct mail_storage *storage_class = NULL;
175 	const char *home;
176 
177 	if (driver == NULL) {
178 		/* no mail_location, autodetect */
179 	} else if (strcmp(driver, "auto") == 0) {
180 		/* explicit autodetection with "auto" driver. */
181 		if (list_set->root_dir != NULL &&
182 		    *list_set->root_dir == '\0') {
183 			/* handle the same as with driver=NULL */
184 			list_set->root_dir = NULL;
185 		}
186 	} else {
187 		storage_class = mail_user_get_storage_class(ns->user, driver);
188 		if (storage_class == NULL) {
189 			*error_r = t_strdup_printf(
190 				"Unknown mail storage driver %s", driver);
191 			return NULL;
192 		}
193 	}
194 
195 	if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
196 		/* no root directory given. is this allowed? */
197 		const struct mailbox_list *list;
198 
199 		list = list_set->layout == NULL ? NULL :
200 			mailbox_list_find_class(list_set->layout);
201 		if (storage_class == NULL &&
202 		    (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
203 			/* autodetection should take care of this */
204 		} else if (storage_class != NULL &&
205 			   (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
206 			/* root not required for this storage */
207 		} else if (list != NULL &&
208 			   (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
209 			/* root not required for this layout */
210 		} else {
211 			*error_r = "Root mail directory not given";
212 			return NULL;
213 		}
214 	}
215 
216 	if (storage_class != NULL) {
217 		storage_class->v.get_list_settings(ns, list_set);
218 		return storage_class;
219 	}
220 
221 	storage_class = mail_storage_autodetect(ns, list_set);
222 	if (storage_class != NULL)
223 		return storage_class;
224 
225 	(void)mail_user_get_home(ns->user, &home);
226 	if (home == NULL || *home == '\0') home = "(not set)";
227 
228 	if (ns->set->location == NULL || *ns->set->location == '\0') {
229 		*error_r = t_strdup_printf(
230 			"Mail storage autodetection failed with home=%s", home);
231 	} else if (str_begins(ns->set->location, "auto:")) {
232 		*error_r = t_strdup_printf(
233 			"Autodetection failed for %s (home=%s)",
234 			ns->set->location, home);
235 	} else {
236 		*error_r = t_strdup_printf(
237 			"Ambiguous mail location setting, "
238 			"don't know what to do with it: %s "
239 			"(try prefixing it with mbox: or maildir:)",
240 			ns->set->location);
241 	}
242 	return NULL;
243 }
244 
245 static int
mail_storage_verify_root(const char * root_dir,const char * dir_type,const char ** error_r)246 mail_storage_verify_root(const char *root_dir, const char *dir_type,
247 			 const char **error_r)
248 {
249 	struct stat st;
250 
251 	if (stat(root_dir, &st) == 0) {
252 		/* exists */
253 		if (S_ISDIR(st.st_mode))
254 			return 0;
255 		*error_r = t_strdup_printf(
256 			"Root mail directory is a file: %s", root_dir);
257 		return -1;
258 	} else if (errno == EACCES) {
259 		*error_r = mail_error_eacces_msg("stat", root_dir);
260 		return -1;
261 	} else if (errno != ENOENT) {
262 		*error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
263 		return -1;
264 	} else {
265 		*error_r = t_strdup_printf(
266 			"Root %s directory doesn't exist: %s", dir_type, root_dir);
267 		return -1;
268 	}
269 }
270 
271 static int
mail_storage_create_root(struct mailbox_list * list,enum mail_storage_flags flags,const char ** error_r)272 mail_storage_create_root(struct mailbox_list *list,
273 			 enum mail_storage_flags flags, const char **error_r)
274 {
275 	const char *root_dir, *type_name, *error;
276 	enum mailbox_list_path_type type;
277 
278 	if (list->set.iter_from_index_dir) {
279 		type = MAILBOX_LIST_PATH_TYPE_INDEX;
280 		type_name = "index";
281 	} else {
282 		type = MAILBOX_LIST_PATH_TYPE_MAILBOX;
283 		type_name = "mail";
284 	}
285 	if (!mailbox_list_get_root_path(list, type, &root_dir)) {
286 		/* storage doesn't use directories (e.g. shared root) */
287 		return 0;
288 	}
289 
290 	if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
291 		if (!event_want_debug_log(list->ns->user->event))
292 			return 0;
293 
294 		/* we don't need to verify, but since debugging is
295 		   enabled, check and log if the root doesn't exist */
296 		if (mail_storage_verify_root(root_dir, type_name, &error) < 0) {
297 			e_debug(list->ns->user->event,
298 				"Namespace %s: Creating storage despite: %s",
299 				list->ns->prefix, error);
300 		}
301 		return 0;
302 	}
303 
304 	if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0) {
305 		/* If the directories don't exist, we'll just autocreate them
306 		   later. */
307 		return 0;
308 	}
309 	return mail_storage_verify_root(root_dir, type_name, error_r);
310 }
311 
312 static bool
mail_storage_match_class(struct mail_storage * storage,const struct mail_storage * storage_class,const struct mailbox_list_settings * set)313 mail_storage_match_class(struct mail_storage *storage,
314 			 const struct mail_storage *storage_class,
315 			 const struct mailbox_list_settings *set)
316 {
317 	if (strcmp(storage->name, storage_class->name) != 0)
318 		return FALSE;
319 
320 	if ((storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
321 	    strcmp(storage->unique_root_dir,
322 	    	(set->root_dir != NULL ? set->root_dir : "")) != 0)
323 		return FALSE;
324 
325 	if (strcmp(storage->name, "shared") == 0) {
326 		/* allow multiple independent shared namespaces */
327 		return FALSE;
328 	}
329 	return TRUE;
330 }
331 
332 static struct mail_storage *
mail_storage_find(struct mail_user * user,const struct mail_storage * storage_class,const struct mailbox_list_settings * set)333 mail_storage_find(struct mail_user *user,
334 		  const struct mail_storage *storage_class,
335 		  const struct mailbox_list_settings *set)
336 {
337 	struct mail_storage *storage = user->storages;
338 
339 	for (; storage != NULL; storage = storage->next) {
340 		if (mail_storage_match_class(storage, storage_class, set))
341 			return storage;
342 	}
343 	return NULL;
344 }
345 
mail_storage_create_full(struct mail_namespace * ns,const char * driver,const char * data,enum mail_storage_flags flags,struct mail_storage ** storage_r,const char ** error_r)346 int mail_storage_create_full(struct mail_namespace *ns, const char *driver,
347 			     const char *data, enum mail_storage_flags flags,
348 			     struct mail_storage **storage_r,
349 			     const char **error_r)
350 {
351 	struct mail_storage *storage_class, *storage = NULL;
352 	struct mailbox_list *list;
353 	struct mailbox_list_settings list_set;
354 	enum mailbox_list_flags list_flags = 0;
355 	const char *p;
356 
357 	if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
358 	    ns->mail_set->pop3_uidl_format != NULL) {
359 		/* if pop3_uidl_format contains %m, we want to keep the
360 		   header MD5 sums stored even if we're not running POP3
361 		   right now. */
362 		p = ns->mail_set->pop3_uidl_format;
363 		while ((p = strchr(p, '%')) != NULL) {
364 			if (p[1] == '%')
365 				p += 2;
366 			else if (var_get_key(++p) == 'm') {
367 				flags |= MAIL_STORAGE_FLAG_KEEP_HEADER_MD5;
368 				break;
369 			}
370 		}
371 	}
372 
373 	mailbox_list_settings_init_defaults(&list_set);
374 	if (data == NULL) {
375 		/* autodetect */
376 	} else if (driver != NULL && strcmp(driver, "shared") == 0) {
377 		/* internal shared namespace */
378 		list_set.root_dir = ns->user->set->base_dir;
379 	} else {
380 		if (driver == NULL)
381 			mail_storage_set_autodetection(&data, &driver);
382 		if (mailbox_list_settings_parse(ns->user, data, &list_set,
383 						error_r) < 0)
384 			return -1;
385 	}
386 
387 	storage_class = mail_storage_get_class(ns, driver, &list_set, flags,
388 					       error_r);
389 	if (storage_class == NULL)
390 		return -1;
391 	i_assert(list_set.layout != NULL);
392 
393 	if (ns->list == NULL) {
394 		/* first storage for namespace */
395 		if (mail_storage_is_mailbox_file(storage_class))
396 			list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
397 		if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0)
398 			list_flags |= MAILBOX_LIST_FLAG_NO_MAIL_FILES;
399 		if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_LIST_DELETES) != 0)
400 			list_flags |= MAILBOX_LIST_FLAG_NO_DELETES;
401 		if (mailbox_list_create(list_set.layout, ns, &list_set,
402 					list_flags, &list, error_r) < 0) {
403 			*error_r = t_strdup_printf("Mailbox list driver %s: %s",
404 						   list_set.layout, *error_r);
405 			return -1;
406 		}
407 		if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) == 0) {
408 			if (mail_storage_create_root(ns->list, flags, error_r) < 0)
409 				return -1;
410 		}
411 	}
412 
413 	storage = mail_storage_find(ns->user, storage_class, &list_set);
414 	if (storage != NULL) {
415 		/* using an existing storage */
416 		storage->refcount++;
417 		mail_namespace_add_storage(ns, storage);
418 		*storage_r = storage;
419 		return 0;
420 	}
421 
422 	storage = storage_class->v.alloc();
423 	if (storage->lost_mailbox_prefix == NULL)
424 		storage->lost_mailbox_prefix = MAIL_STORAGE_LOST_MAILBOX_PREFIX;
425 	storage->refcount = 1;
426 	storage->storage_class = storage_class;
427 	storage->user = ns->user;
428 	storage->set = ns->mail_set;
429 	storage->flags = flags;
430 	storage->event = event_create(ns->user->event);
431 	if (storage_class->event_category != NULL)
432 		event_add_category(storage->event, storage_class->event_category);
433 	p_array_init(&storage->module_contexts, storage->pool, 5);
434 
435 	if (storage->v.create != NULL &&
436 	    storage->v.create(storage, ns, error_r) < 0) {
437 		*error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
438 		event_unref(&storage->event);
439 		pool_unref(&storage->pool);
440 		return -1;
441 	}
442 
443 	/* If storage supports list index rebuild,
444 	   provide default mailboxes_fs unless storage
445 	   wants to use its own. */
446 	if (storage->v.list_index_rebuild != NULL &&
447 	    storage->mailboxes_fs == NULL) {
448 		struct fs_settings fs_set;
449 		struct ssl_iostream_settings ssl_set;
450 		const char *error;
451 		i_zero(&fs_set);
452 
453 		mail_user_init_fs_settings(storage->user, &fs_set, &ssl_set);
454 		if (fs_init("posix", "", &fs_set, &storage->mailboxes_fs,
455 			    &error) < 0) {
456 			*error_r = t_strdup_printf("fs_init(posix) failed: %s", error);
457 			storage->v.destroy(storage);
458 			return -1;
459 		}
460 	}
461 
462 	T_BEGIN {
463 		hook_mail_storage_created(storage);
464 	} T_END;
465 
466 	i_assert(storage->unique_root_dir != NULL ||
467 		 (storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) == 0);
468 	DLLIST_PREPEND(&ns->user->storages, storage);
469 	mail_namespace_add_storage(ns, storage);
470 	*storage_r = storage;
471 	return 0;
472 }
473 
mail_storage_create(struct mail_namespace * ns,const char * driver,enum mail_storage_flags flags,const char ** error_r)474 int mail_storage_create(struct mail_namespace *ns, const char *driver,
475 			enum mail_storage_flags flags, const char **error_r)
476 {
477 	struct mail_storage *storage;
478 
479 	return mail_storage_create_full(ns, driver, ns->set->location,
480 					flags, &storage, error_r);
481 }
482 
mail_storage_unref(struct mail_storage ** _storage)483 void mail_storage_unref(struct mail_storage **_storage)
484 {
485 	struct mail_storage *storage = *_storage;
486 
487 	i_assert(storage->refcount > 0);
488 
489 	/* set *_storage=NULL only after calling destroy() callback.
490 	   for example mdbox wants to access ns->storage */
491 	if (--storage->refcount > 0) {
492 		*_storage = NULL;
493 		return;
494 	}
495 
496 	if (storage->mailboxes != NULL) {
497 		i_panic("Trying to deinit storage without freeing mailbox %s",
498 			storage->mailboxes->vname);
499 	}
500 	if (storage->obj_refcount != 0)
501 		i_panic("Trying to deinit storage before freeing its objects");
502 
503 	DLLIST_REMOVE(&storage->user->storages, storage);
504 
505 	storage->v.destroy(storage);
506 	i_free(storage->last_internal_error);
507 	i_free(storage->error_string);
508 	if (array_is_created(&storage->error_stack)) {
509 		i_assert(array_count(&storage->error_stack) == 0);
510 		array_free(&storage->error_stack);
511 	}
512 	fs_unref(&storage->mailboxes_fs);
513 	event_unref(&storage->event);
514 
515 	*_storage = NULL;
516 	pool_unref(&storage->pool);
517 
518 	mail_index_alloc_cache_destroy_unrefed();
519 }
520 
mail_storage_obj_ref(struct mail_storage * storage)521 void mail_storage_obj_ref(struct mail_storage *storage)
522 {
523 	i_assert(storage->refcount > 0);
524 
525 	if (storage->obj_refcount++ == 0)
526 		mail_user_ref(storage->user);
527 }
528 
mail_storage_obj_unref(struct mail_storage * storage)529 void mail_storage_obj_unref(struct mail_storage *storage)
530 {
531 	i_assert(storage->refcount > 0);
532 	i_assert(storage->obj_refcount > 0);
533 
534 	if (--storage->obj_refcount == 0) {
535 		struct mail_user *user = storage->user;
536 		mail_user_unref(&user);
537 	}
538 }
539 
mail_storage_clear_error(struct mail_storage * storage)540 void mail_storage_clear_error(struct mail_storage *storage)
541 {
542 	i_free_and_null(storage->error_string);
543 
544 	i_free(storage->last_internal_error);
545 	storage->last_error_is_internal = FALSE;
546 	storage->error = MAIL_ERROR_NONE;
547 }
548 
mail_storage_set_error(struct mail_storage * storage,enum mail_error error,const char * string)549 void mail_storage_set_error(struct mail_storage *storage,
550 			    enum mail_error error, const char *string)
551 {
552 	if (storage->error_string != string) {
553 		i_free(storage->error_string);
554 		storage->error_string = i_strdup(string);
555 	}
556 	storage->last_error_is_internal = FALSE;
557 	storage->error = error;
558 }
559 
mail_storage_set_internal_error(struct mail_storage * storage)560 void mail_storage_set_internal_error(struct mail_storage *storage)
561 {
562 	const char *str;
563 
564 	str = t_strflocaltime(MAIL_ERRSTR_CRITICAL_MSG_STAMP, ioloop_time);
565 
566 	i_free(storage->error_string);
567 	storage->error_string = i_strdup(str);
568 	storage->error = MAIL_ERROR_TEMP;
569 
570 	/* this function doesn't set last_internal_error, so
571 	   last_error_is_internal can't be TRUE. */
572 	storage->last_error_is_internal = FALSE;
573 	i_free(storage->last_internal_error);
574 }
575 
mail_storage_set_critical(struct mail_storage * storage,const char * fmt,...)576 void mail_storage_set_critical(struct mail_storage *storage,
577 			       const char *fmt, ...)
578 {
579 	char *old_error = storage->error_string;
580 	char *old_internal_error = storage->last_internal_error;
581 	va_list va;
582 
583 	storage->error_string = NULL;
584 	storage->last_internal_error = NULL;
585 	/* critical errors may contain sensitive data, so let user
586 	   see only "Internal error" with a timestamp to make it
587 	   easier to look from log files the actual error message. */
588 	mail_storage_set_internal_error(storage);
589 
590 	va_start(va, fmt);
591 	storage->last_internal_error = i_strdup_vprintf(fmt, va);
592 	va_end(va);
593 	storage->last_error_is_internal = TRUE;
594 	e_error(storage->event, "%s", storage->last_internal_error);
595 
596 	/* free the old_error and old_internal_error only after the new error
597 	   is generated, because they may be one of the parameters. */
598 	i_free(old_error);
599 	i_free(old_internal_error);
600 }
601 
mailbox_set_critical(struct mailbox * box,const char * fmt,...)602 void mailbox_set_critical(struct mailbox *box, const char *fmt, ...)
603 {
604 	va_list va;
605 
606 	va_start(va, fmt);
607 	T_BEGIN {
608 		mail_storage_set_critical(box->storage, "Mailbox %s: %s",
609 			box->vname, t_strdup_vprintf(fmt, va));
610 	} T_END;
611 	va_end(va);
612 }
613 
mail_set_critical(struct mail * mail,const char * fmt,...)614 void mail_set_critical(struct mail *mail, const char *fmt, ...)
615 {
616 	va_list va;
617 
618 	va_start(va, fmt);
619 	T_BEGIN {
620 		if (mail->saving) {
621 			mailbox_set_critical(mail->box, "Saving mail: %s",
622 				t_strdup_vprintf(fmt, va));
623 		} else {
624 			mailbox_set_critical(mail->box, "UID=%u: %s",
625 				mail->uid, t_strdup_vprintf(fmt, va));
626 		}
627 	} T_END;
628 	va_end(va);
629 }
630 
mail_storage_get_last_internal_error(struct mail_storage * storage,enum mail_error * error_r)631 const char *mail_storage_get_last_internal_error(struct mail_storage *storage,
632 						 enum mail_error *error_r)
633 {
634 	if (error_r != NULL)
635 		*error_r = storage->error;
636 	if (storage->last_error_is_internal) {
637 		i_assert(storage->last_internal_error != NULL);
638 		return storage->last_internal_error;
639 	}
640 	return mail_storage_get_last_error(storage, error_r);
641 }
642 
mailbox_get_last_internal_error(struct mailbox * box,enum mail_error * error_r)643 const char *mailbox_get_last_internal_error(struct mailbox *box,
644 					    enum mail_error *error_r)
645 {
646 	return mail_storage_get_last_internal_error(mailbox_get_storage(box),
647 						    error_r);
648 }
649 
mail_storage_copy_error(struct mail_storage * dest,struct mail_storage * src)650 void mail_storage_copy_error(struct mail_storage *dest,
651 			     struct mail_storage *src)
652 {
653 	const char *str;
654 	enum mail_error error;
655 
656 	if (src == dest)
657 		return;
658 
659 	str = mail_storage_get_last_error(src, &error);
660 	mail_storage_set_error(dest, error, str);
661 }
662 
mail_storage_copy_list_error(struct mail_storage * storage,struct mailbox_list * list)663 void mail_storage_copy_list_error(struct mail_storage *storage,
664 				  struct mailbox_list *list)
665 {
666 	const char *str;
667 	enum mail_error error;
668 
669 	str = mailbox_list_get_last_error(list, &error);
670 	mail_storage_set_error(storage, error, str);
671 }
672 
mailbox_set_index_error(struct mailbox * box)673 void mailbox_set_index_error(struct mailbox *box)
674 {
675 	if (mail_index_is_deleted(box->index)) {
676 		mailbox_set_deleted(box);
677 		mail_index_reset_error(box->index);
678 	} else {
679 		mail_storage_set_index_error(box->storage, box->index);
680 	}
681 }
682 
mail_storage_set_index_error(struct mail_storage * storage,struct mail_index * index)683 void mail_storage_set_index_error(struct mail_storage *storage,
684 				  struct mail_index *index)
685 {
686 	const char *index_error;
687 
688 	mail_storage_set_internal_error(storage);
689 	/* use the lib-index's error as our internal error string */
690 	index_error = mail_index_get_error_message(index);
691 	if (index_error == NULL)
692 		index_error = "BUG: Unknown internal index error";
693 	storage->last_internal_error = i_strdup(index_error);
694 	storage->last_error_is_internal = TRUE;
695 	mail_index_reset_error(index);
696 }
697 
698 const struct mail_storage_settings *
mail_storage_get_settings(struct mail_storage * storage)699 mail_storage_get_settings(struct mail_storage *storage)
700 {
701 	return storage->set;
702 }
703 
mail_storage_get_user(struct mail_storage * storage)704 struct mail_user *mail_storage_get_user(struct mail_storage *storage)
705 {
706 	return storage->user;
707 }
708 
mail_storage_set_callbacks(struct mail_storage * storage,struct mail_storage_callbacks * callbacks,void * context)709 void mail_storage_set_callbacks(struct mail_storage *storage,
710 				struct mail_storage_callbacks *callbacks,
711 				void *context)
712 {
713 	storage->callbacks = *callbacks;
714 	storage->callback_context = context;
715 }
716 
mail_storage_purge(struct mail_storage * storage)717 int mail_storage_purge(struct mail_storage *storage)
718 {
719 	return storage->v.purge == NULL ? 0 :
720 		storage->v.purge(storage);
721 }
722 
mail_storage_get_last_error(struct mail_storage * storage,enum mail_error * error_r)723 const char *mail_storage_get_last_error(struct mail_storage *storage,
724 					enum mail_error *error_r)
725 {
726 	/* We get here only in error situations, so we have to return some
727 	   error. If storage->error is NONE, it means we forgot to set it at
728 	   some point.. */
729 	if (storage->error == MAIL_ERROR_NONE) {
730 		if (error_r != NULL)
731 			*error_r = MAIL_ERROR_TEMP;
732 		return storage->error_string != NULL ? storage->error_string :
733 			"BUG: Unknown internal error";
734 	}
735 
736 	if (storage->error_string == NULL) {
737 		/* This shouldn't happen.. */
738 		storage->error_string =
739 			i_strdup_printf("BUG: Unknown 0x%x error",
740 					storage->error);
741 	}
742 
743 	if (error_r != NULL)
744 		*error_r = storage->error;
745 	return storage->error_string;
746 }
747 
mailbox_get_last_error(struct mailbox * box,enum mail_error * error_r)748 const char *mailbox_get_last_error(struct mailbox *box,
749 				   enum mail_error *error_r)
750 {
751 	return mail_storage_get_last_error(box->storage, error_r);
752 }
753 
mailbox_get_last_mail_error(struct mailbox * box)754 enum mail_error mailbox_get_last_mail_error(struct mailbox *box)
755 {
756 	enum mail_error error;
757 
758 	mail_storage_get_last_error(box->storage, &error);
759 	return error;
760 }
761 
mail_storage_last_error_push(struct mail_storage * storage)762 void mail_storage_last_error_push(struct mail_storage *storage)
763 {
764 	struct mail_storage_error *err;
765 
766 	if (!array_is_created(&storage->error_stack))
767 		i_array_init(&storage->error_stack, 2);
768 	err = array_append_space(&storage->error_stack);
769 	err->error_string = i_strdup(storage->error_string);
770 	err->error = storage->error;
771 	err->last_error_is_internal = storage->last_error_is_internal;
772 	if (err->last_error_is_internal)
773 		err->last_internal_error = i_strdup(storage->last_internal_error);
774 }
775 
mail_storage_last_error_pop(struct mail_storage * storage)776 void mail_storage_last_error_pop(struct mail_storage *storage)
777 {
778 	unsigned int count = array_count(&storage->error_stack);
779 	const struct mail_storage_error *err =
780 		array_idx(&storage->error_stack, count-1);
781 
782 	i_free(storage->error_string);
783 	i_free(storage->last_internal_error);
784 	storage->error_string = err->error_string;
785 	storage->error = err->error;
786 	storage->last_error_is_internal = err->last_error_is_internal;
787 	storage->last_internal_error = err->last_internal_error;
788 	array_delete(&storage->error_stack, count-1, 1);
789 }
790 
mail_storage_is_mailbox_file(struct mail_storage * storage)791 bool mail_storage_is_mailbox_file(struct mail_storage *storage)
792 {
793 	return (storage->class_flags &
794 		MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
795 }
796 
mail_storage_set_error_from_errno(struct mail_storage * storage)797 bool mail_storage_set_error_from_errno(struct mail_storage *storage)
798 {
799 	const char *error_string;
800 	enum mail_error error;
801 
802 	if (!mail_error_from_errno(&error, &error_string))
803 		return FALSE;
804 	if (event_want_debug_log(storage->event) && error != MAIL_ERROR_NOTFOUND) {
805 		/* debugging is enabled - admin may be debugging a
806 		   (permission) problem, so return FALSE to get the caller to
807 		   log the full error message. */
808 		return FALSE;
809 	}
810 
811 	mail_storage_set_error(storage, error, error_string);
812 	return TRUE;
813 }
814 
815 const struct mailbox_settings *
mailbox_settings_find(struct mail_namespace * ns,const char * vname)816 mailbox_settings_find(struct mail_namespace *ns, const char *vname)
817 {
818 	struct mailbox_settings *box_set;
819 
820 	if (!array_is_created(&ns->set->mailboxes))
821 		return NULL;
822 
823 	if (ns->prefix_len > 0 &&
824 	    strncmp(ns->prefix, vname, ns->prefix_len-1) == 0) {
825 		if (vname[ns->prefix_len-1] == mail_namespace_get_sep(ns))
826 			vname += ns->prefix_len;
827 		else if (vname[ns->prefix_len-1] == '\0') {
828 			/* namespace prefix itself */
829 			vname = "";
830 		}
831 	}
832 	array_foreach_elem(&ns->set->mailboxes, box_set) {
833 		if (strcmp(box_set->name, vname) == 0)
834 			return box_set;
835 	}
836 	return NULL;
837 }
838 
mailbox_alloc(struct mailbox_list * list,const char * vname,enum mailbox_flags flags)839 struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
840 			      enum mailbox_flags flags)
841 {
842 	struct mailbox_list *new_list = list;
843 	struct mail_storage *storage;
844 	struct mailbox *box;
845 	enum mail_error open_error = 0;
846 	const char *errstr = NULL;
847 
848 	i_assert(uni_utf8_str_is_valid(vname));
849 
850 	if (strncasecmp(vname, "INBOX", 5) == 0 &&
851 	    !str_begins(vname, "INBOX")) {
852 		/* make sure INBOX shows up in uppercase everywhere. do this
853 		   regardless of whether we're in inbox=yes namespace, because
854 		   clients expect INBOX to be case insensitive regardless of
855 		   server's internal configuration. */
856 		if (vname[5] == '\0')
857 			vname = "INBOX";
858 		else if (vname[5] != mail_namespace_get_sep(list->ns))
859 			/* not INBOX prefix */ ;
860 		else if (strncasecmp(list->ns->prefix, vname, 6) == 0 &&
861 			 !str_begins(list->ns->prefix, "INBOX")) {
862 			mailbox_list_set_critical(list,
863 				"Invalid server configuration: "
864 				"Namespace prefix=%s must be uppercase INBOX",
865 				list->ns->prefix);
866 			open_error = MAIL_ERROR_TEMP;
867 		} else {
868 			vname = t_strconcat("INBOX", vname + 5, NULL);
869 		}
870 	}
871 
872 	T_BEGIN {
873 		if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
874 			/* do a delayed failure at mailbox_open() */
875 			storage = mail_namespace_get_default_storage(list->ns);
876 			errstr = mailbox_list_get_last_error(new_list, &open_error);
877 			errstr = t_strdup(errstr);
878 		}
879 
880 		box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
881 		box->set = mailbox_settings_find(new_list->ns, vname);
882 		box->open_error = open_error;
883 		if (open_error != 0)
884 			mail_storage_set_error(storage, open_error, errstr);
885 		hook_mailbox_allocated(box);
886 	} T_END;
887 
888 	DLLIST_PREPEND(&box->storage->mailboxes, box);
889 	mail_storage_obj_ref(box->storage);
890 	return box;
891 }
892 
mailbox_alloc_guid(struct mailbox_list * list,const guid_128_t guid,enum mailbox_flags flags)893 struct mailbox *mailbox_alloc_guid(struct mailbox_list *list,
894 				   const guid_128_t guid,
895 				   enum mailbox_flags flags)
896 {
897 	struct mailbox *box = NULL;
898 	struct mailbox_metadata metadata;
899 	enum mail_error open_error = MAIL_ERROR_TEMP;
900 	const char *vname;
901 
902 	if (mailbox_guid_cache_find(list, guid, &vname) < 0) {
903 		vname = NULL;
904 	} else if (vname != NULL) {
905 		box = mailbox_alloc(list, vname, flags);
906 		if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID,
907 					 &metadata) < 0) {
908 		} else if (memcmp(metadata.guid, guid,
909 				  sizeof(metadata.guid)) != 0) {
910 			/* GUID mismatch, refresh cache and try again */
911 			mailbox_free(&box);
912 			mailbox_guid_cache_refresh(list);
913 			return mailbox_alloc_guid(list, guid, flags);
914 		} else {
915 			/* successfully opened the correct mailbox */
916 			return box;
917 		}
918 		e_error(list->ns->user->event, "mailbox_alloc_guid(%s): "
919 			"Couldn't verify mailbox GUID: %s",
920 			guid_128_to_string(guid),
921 			mailbox_get_last_internal_error(box, NULL));
922 		vname = NULL;
923 		mailbox_free(&box);
924 	} else {
925 		vname = t_strdup_printf("(nonexistent mailbox with GUID=%s)",
926 					guid_128_to_string(guid));
927 		open_error = MAIL_ERROR_NOTFOUND;
928 	}
929 
930 	if (vname == NULL) {
931 		vname = t_strdup_printf("(error in mailbox with GUID=%s)",
932 					guid_128_to_string(guid));
933 	}
934 	box = mailbox_alloc(list, vname, flags);
935 	box->open_error = open_error;
936 	return box;
937 }
938 
939 static bool
str_contains_special_use(const char * str,const char * special_use)940 str_contains_special_use(const char *str, const char *special_use)
941 {
942 	const char *const *uses;
943 
944 	i_assert(special_use != NULL);
945 	if (*special_use != '\\')
946 		return FALSE;
947 
948 	bool ret;
949 	T_BEGIN {
950 		uses = t_strsplit_spaces(str, " ");
951 		ret = str_array_icase_find(uses, special_use);
952 	} T_END;
953 	return ret;
954 }
955 
956 static int
namespace_find_special_use(struct mail_namespace * ns,const char * special_use,const char ** vname_r,enum mail_error * error_code_r)957 namespace_find_special_use(struct mail_namespace *ns, const char *special_use,
958 		           const char **vname_r, enum mail_error *error_code_r)
959 {
960 	struct mailbox_list *list = ns->list;
961 	struct mailbox_list_iterate_context *ctx;
962 	const struct mailbox_info *info;
963 	int ret = 0;
964 
965 	*vname_r = NULL;
966 	*error_code_r = MAIL_ERROR_NONE;
967 
968 	if (!ns->special_use_mailboxes)
969 		return 0;
970 	if (!HAS_ALL_BITS(ns->type, MAIL_NAMESPACE_TYPE_PRIVATE))
971 		return 0;
972 
973 	ctx = mailbox_list_iter_init(list, "*",
974 		MAILBOX_LIST_ITER_SELECT_SPECIALUSE |
975 		MAILBOX_LIST_ITER_RETURN_SPECIALUSE);
976 	while ((info = mailbox_list_iter_next(ctx)) != NULL) {
977 		if ((info->flags &
978 		     (MAILBOX_NOSELECT | MAILBOX_NONEXISTENT)) != 0)
979 			continue;
980 		/* iter can only return mailboxes that have non-empty
981 		   special-use */
982 		i_assert(info->special_use != NULL &&
983 			 *info->special_use != '\0');
984 
985 		if (str_contains_special_use(info->special_use, special_use)) {
986 			*vname_r = t_strdup(info->vname);
987 			ret = 1;
988 			break;
989 		}
990 	}
991 	if (mailbox_list_iter_deinit(&ctx) < 0) {
992 		const char *error;
993 
994 		error = mailbox_list_get_last_error(ns->list, error_code_r);
995 		e_error(ns->user->event,
996 			"Failed to find mailbox with SPECIAL-USE flag '%s' "
997 			"in namespace '%s': %s",
998 			special_use, ns->prefix, error);
999 		return -1;
1000 	}
1001 	return ret;
1002 }
1003 
1004 static int
namespaces_find_special_use(struct mail_namespace * namespaces,const char * special_use,struct mail_namespace ** ns_r,const char ** vname_r,enum mail_error * error_code_r)1005 namespaces_find_special_use(struct mail_namespace *namespaces,
1006 			    const char *special_use,
1007 			    struct mail_namespace **ns_r,
1008 			    const char **vname_r, enum mail_error *error_code_r)
1009 {
1010 	struct mail_namespace *ns_inbox;
1011 	int ret;
1012 
1013 	*error_code_r = MAIL_ERROR_NONE;
1014 	*vname_r = NULL;
1015 
1016 	/* check user's INBOX namespace first */
1017 	*ns_r = ns_inbox = mail_namespace_find_inbox(namespaces);
1018 	ret = namespace_find_special_use(*ns_r, special_use,
1019 					 vname_r, error_code_r);
1020 	if (ret != 0)
1021 		return ret;
1022 
1023 	/* check other namespaces */
1024 	for (*ns_r = namespaces; *ns_r != NULL; *ns_r = (*ns_r)->next) {
1025 		if (*ns_r == ns_inbox) {
1026 			/* already checked */
1027 			continue;
1028 		}
1029 		ret = namespace_find_special_use(*ns_r, special_use,
1030 						 vname_r, error_code_r);
1031 		if (ret != 0)
1032 			return ret;
1033 	}
1034 
1035 	*ns_r = ns_inbox;
1036 	return 0;
1037 }
1038 
1039 struct mailbox *
mailbox_alloc_for_user(struct mail_user * user,const char * mname,enum mailbox_flags flags)1040 mailbox_alloc_for_user(struct mail_user *user, const char *mname,
1041 		       enum mailbox_flags flags)
1042 {
1043 	struct mail_namespace *ns;
1044 	struct mailbox *box;
1045 	const char *vname;
1046 	enum mail_error open_error = MAIL_ERROR_NONE;
1047 	int ret;
1048 
1049 	if (HAS_ALL_BITS(flags, MAILBOX_FLAG_SPECIAL_USE)) {
1050 		ret = namespaces_find_special_use(user->namespaces, mname,
1051 						  &ns, &vname, &open_error);
1052 		if (ret < 0) {
1053 			i_assert(open_error != MAIL_ERROR_NONE);
1054 			vname = t_strdup_printf(
1055 				"(error finding mailbox with SPECIAL-USE=%s)",
1056 				mname);
1057 		} else if (ret == 0) {
1058 			i_assert(open_error == MAIL_ERROR_NONE);
1059 			vname = t_strdup_printf(
1060 				"(nonexistent mailbox with SPECIAL-USE=%s)",
1061 				mname);
1062 			open_error = MAIL_ERROR_NOTFOUND;
1063 		}
1064 	} else {
1065 		vname = mname;
1066 		ns = mail_namespace_find(user->namespaces, mname);
1067 	}
1068 
1069 	if (HAS_ALL_BITS(flags, MAILBOX_FLAG_POST_SESSION)) {
1070 		flags |= MAILBOX_FLAG_SAVEONLY;
1071 
1072 		if (strcmp(vname, ns->prefix) == 0 &&
1073 		    (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
1074 			/* delivering to a namespace prefix means we actually
1075 			   want to deliver to the INBOX instead */
1076 			vname = "INBOX";
1077 			ns = mail_namespace_find_inbox(user->namespaces);
1078 		}
1079 
1080 		if (strcasecmp(vname, "INBOX") == 0) {
1081 			/* deliveries to INBOX must always succeed,
1082 			   regardless of ACLs */
1083 			flags |= MAILBOX_FLAG_IGNORE_ACLS;
1084 		}
1085 	}
1086 
1087 	i_assert(ns != NULL);
1088 	box = mailbox_alloc(ns->list, vname, flags);
1089 	if (open_error != MAIL_ERROR_NONE)
1090 		box->open_error = open_error;
1091 	return box;
1092 }
1093 
mailbox_set_reason(struct mailbox * box,const char * reason)1094 void mailbox_set_reason(struct mailbox *box, const char *reason)
1095 {
1096 	i_assert(reason != NULL);
1097 
1098 	box->reason = p_strdup(box->pool, reason);
1099 }
1100 
mailbox_is_autocreated(struct mailbox * box)1101 bool mailbox_is_autocreated(struct mailbox *box)
1102 {
1103 	if (box->inbox_user)
1104 		return TRUE;
1105 	if ((box->flags & MAILBOX_FLAG_AUTO_CREATE) != 0)
1106 		return TRUE;
1107 	return box->set != NULL &&
1108 		strcmp(box->set->autocreate, MAILBOX_SET_AUTO_NO) != 0;
1109 }
1110 
mailbox_is_autosubscribed(struct mailbox * box)1111 bool mailbox_is_autosubscribed(struct mailbox *box)
1112 {
1113 	if ((box->flags & MAILBOX_FLAG_AUTO_SUBSCRIBE) != 0)
1114 		return TRUE;
1115 	return box->set != NULL &&
1116 		strcmp(box->set->autocreate, MAILBOX_SET_AUTO_SUBSCRIBE) == 0;
1117 }
1118 
mailbox_autocreate(struct mailbox * box)1119 static int mailbox_autocreate(struct mailbox *box)
1120 {
1121 	const char *errstr;
1122 	enum mail_error error;
1123 
1124 	if (mailbox_create(box, NULL, FALSE) < 0) {
1125 		errstr = mailbox_get_last_internal_error(box, &error);
1126 		if (error == MAIL_ERROR_NOTFOUND && box->acl_no_lookup_right) {
1127 			/* ACL prevents creating this mailbox */
1128 			return -1;
1129 		}
1130 		if (error != MAIL_ERROR_EXISTS) {
1131 			mailbox_set_critical(box,
1132 				"Failed to autocreate mailbox: %s",
1133 				errstr);
1134 			return -1;
1135 		}
1136 	} else if (mailbox_is_autosubscribed(box)) {
1137 		if (mailbox_set_subscribed(box, TRUE) < 0) {
1138 			mailbox_set_critical(box,
1139 				"Failed to autosubscribe to mailbox: %s",
1140 				mailbox_get_last_internal_error(box, NULL));
1141 			return -1;
1142 		}
1143 	}
1144 	return 0;
1145 }
1146 
mailbox_autocreate_and_reopen(struct mailbox * box)1147 static int mailbox_autocreate_and_reopen(struct mailbox *box)
1148 {
1149 	int ret;
1150 
1151 	if (mailbox_autocreate(box) < 0)
1152 		return -1;
1153 	mailbox_close(box);
1154 
1155 	ret = box->v.open(box);
1156 	if (ret < 0 && box->inbox_user && !box->acl_no_lookup_right &&
1157 	    !box->storage->user->inbox_open_error_logged) {
1158 		box->storage->user->inbox_open_error_logged = TRUE;
1159 		mailbox_set_critical(box,
1160 			"Opening INBOX failed: %s",
1161 			mailbox_get_last_internal_error(box, NULL));
1162 	}
1163 	return ret;
1164 }
1165 
1166 static bool
mailbox_name_verify_extra_separators(const char * vname,char sep,const char ** error_r)1167 mailbox_name_verify_extra_separators(const char *vname, char sep,
1168 				     const char **error_r)
1169 {
1170 	unsigned int i;
1171 	bool prev_sep = FALSE;
1172 
1173 	/* Make sure the vname doesn't have extra separators:
1174 
1175 	   1) Must not have adjacent separators. If we allow these, these could
1176 	   end up pointing to existing mailboxes due to kernel ignoring
1177 	   duplicate '/' in paths. However, this might cause us to handle some
1178 	   of our own checks wrong, such as skipping ACLs.
1179 
1180 	   2) Must not end with separator. Similar reasoning as above.
1181 	*/
1182 	for (i = 0; vname[i] != '\0'; i++) {
1183 		if (vname[i] == sep) {
1184 			if (prev_sep) {
1185 				*error_r = "Has adjacent hierarchy separators";
1186 				return FALSE;
1187 			}
1188 			prev_sep = TRUE;
1189 		} else {
1190 			prev_sep = FALSE;
1191 		}
1192 	}
1193 	if (prev_sep && i > 0) {
1194 		*error_r = "Ends with hierarchy separator";
1195 		return FALSE;
1196 	}
1197 	return TRUE;
1198 }
1199 
1200 static bool
mailbox_verify_name_prefix(struct mail_namespace * ns,const char ** vnamep,const char ** error_r)1201 mailbox_verify_name_prefix(struct mail_namespace *ns, const char **vnamep,
1202 			   const char **error_r)
1203 {
1204 	const char *vname = *vnamep;
1205 
1206 	if (ns->prefix_len == 0)
1207 		return TRUE;
1208 
1209 	/* vname is either "namespace/box" or "namespace" */
1210 	if (strncmp(vname, ns->prefix, ns->prefix_len-1) != 0 ||
1211 	    (vname[ns->prefix_len-1] != '\0' &&
1212 	     vname[ns->prefix_len-1] != ns->prefix[ns->prefix_len-1])) {
1213 		/* User input shouldn't normally be able to get us in
1214 		   here. The main reason this isn't an assert is to
1215 		   allow any input at all to mailbox_verify_*_name()
1216 		   without crashing. */
1217 		*error_r = t_strdup_printf("Missing namespace prefix '%s'",
1218 					   ns->prefix);
1219 		return FALSE;
1220 	}
1221 	vname += ns->prefix_len - 1;
1222 	if (vname[0] != '\0') {
1223 		i_assert(vname[0] == ns->prefix[ns->prefix_len-1]);
1224 		vname++;
1225 
1226 		if (vname[0] == '\0') {
1227 			/* "namespace/" isn't a valid mailbox name. */
1228 			*error_r = "Ends with hierarchy separator";
1229 			return FALSE;
1230 		}
1231 	}
1232 	*vnamep = vname;
1233 	return TRUE;
1234 }
1235 
mailbox_verify_name_int(struct mailbox * box)1236 static int mailbox_verify_name_int(struct mailbox *box)
1237 {
1238 	struct mail_namespace *ns = box->list->ns;
1239 	const char *error, *vname = box->vname;
1240 	char list_sep, ns_sep;
1241 
1242 	if (box->inbox_user) {
1243 		/* this is INBOX - don't bother with further checks */
1244 		return 0;
1245 	}
1246 
1247 	/* Verify the namespace prefix here. Change vname to skip the prefix
1248 	   for the following checks. */
1249 	if (!mailbox_verify_name_prefix(box->list->ns, &vname, &error)) {
1250 		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1251 			t_strdup_printf("Invalid mailbox name '%s': %s",
1252 					str_sanitize(vname, 80), error));
1253 		return -1;
1254 	}
1255 
1256 	list_sep = mailbox_list_get_hierarchy_sep(box->list);
1257 	ns_sep = mail_namespace_get_sep(ns);
1258 
1259 	/* If namespace { separator } differs from the mailbox_list separator,
1260 	   the list separator can't actually be used in the mailbox name
1261 	   unless it's escaped with storage_name_escape_char. For example if
1262 	   namespace separator is '/' and LAYOUT=Maildir++ has '.' as the
1263 	   separator, there's no way to use '.' in the mailbox name (without
1264 	   escaping) because it would end up becoming a hierarchy separator. */
1265 	if (ns_sep != list_sep &&
1266 	    box->list->set.storage_name_escape_char == '\0' &&
1267 	    strchr(vname, list_sep) != NULL) {
1268 		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, t_strdup_printf(
1269 			"Character not allowed in mailbox name: '%c'", list_sep));
1270 		return -1;
1271 	}
1272 	/* vname must not begin with the hierarchy separator normally.
1273 	   For example we don't want to allow accessing /etc/passwd. However,
1274 	   if mail_full_filesystem_access=yes, we do actually want to allow
1275 	   that. */
1276 	if (vname[0] == ns_sep &&
1277 	    !box->storage->set->mail_full_filesystem_access) {
1278 		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1279 			"Invalid mailbox name: Begins with hierarchy separator");
1280 		return -1;
1281 	}
1282 
1283 	if (!mailbox_name_verify_extra_separators(vname, ns_sep, &error) ||
1284 	    !mailbox_list_is_valid_name(box->list, box->name, &error)) {
1285 		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1286 			t_strdup_printf("Invalid mailbox name: %s", error));
1287 		return -1;
1288 	}
1289 	return 0;
1290 }
1291 
mailbox_verify_name(struct mailbox * box)1292 int mailbox_verify_name(struct mailbox *box)
1293 {
1294 	int ret;
1295 	T_BEGIN {
1296 		ret = mailbox_verify_name_int(box);
1297 	} T_END;
1298 	return ret;
1299 }
1300 
mailbox_verify_existing_name_int(struct mailbox * box)1301 static int mailbox_verify_existing_name_int(struct mailbox *box)
1302 {
1303 	const char *path;
1304 
1305 	if (box->opened)
1306 		return 0;
1307 
1308 	if (mailbox_verify_name(box) < 0)
1309 		return -1;
1310 
1311 	/* Make sure box->_path is set, so mailbox_get_path() works from
1312 	   now on. Note that this may also fail with some backends if the
1313 	   mailbox doesn't exist. */
1314 	if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX, &path) < 0) {
1315 		if (box->storage->error != MAIL_ERROR_NOTFOUND ||
1316 		    !mailbox_is_autocreated(box))
1317 			return -1;
1318 		/* if this is an autocreated mailbox, create it now */
1319 		if (mailbox_autocreate(box) < 0)
1320 			return -1;
1321 		mailbox_close(box);
1322 		if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
1323 					&path) < 0)
1324 			return -1;
1325 	}
1326 	return 0;
1327 }
1328 
mailbox_verify_existing_name(struct mailbox * box)1329 static int mailbox_verify_existing_name(struct mailbox *box)
1330 {
1331 	int ret;
1332 	T_BEGIN {
1333 		ret = mailbox_verify_existing_name_int(box);
1334 	} T_END;
1335 	return ret;
1336 }
1337 
mailbox_name_has_control_chars(const char * name)1338 static bool mailbox_name_has_control_chars(const char *name)
1339 {
1340 	const char *p;
1341 
1342 	for (p = name; *p != '\0'; p++) {
1343 		if ((unsigned char)*p < ' ')
1344 			return TRUE;
1345 	}
1346 	return FALSE;
1347 }
1348 
mailbox_skip_create_name_restrictions(struct mailbox * box,bool set)1349 void mailbox_skip_create_name_restrictions(struct mailbox *box, bool set)
1350 {
1351 	box->skip_create_name_restrictions = set;
1352 }
1353 
mailbox_verify_create_name(struct mailbox * box)1354 int mailbox_verify_create_name(struct mailbox *box)
1355 {
1356 	/* mailbox_alloc() already checks that vname is valid UTF8,
1357 	   so we don't need to verify that.
1358 
1359 	   check vname instead of storage name, because vname is what is
1360 	   visible to users, while storage name may be a fixed length GUID. */
1361 	if (mailbox_verify_name(box) < 0)
1362 		return -1;
1363 	if (box->skip_create_name_restrictions)
1364 		return 0;
1365 	if (mailbox_name_has_control_chars(box->vname)) {
1366 		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1367 			"Control characters not allowed in new mailbox names");
1368 		return -1;
1369 	}
1370 	if (strlen(box->vname) > MAILBOX_LIST_NAME_MAX_LENGTH) {
1371 		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1372 				       "Mailbox name too long");
1373 		return -1;
1374 	}
1375 	/* check individual component names, too */
1376 	const char *old_name = box->name;
1377 	const char *name;
1378 	const char sep = mailbox_list_get_hierarchy_sep(box->list);
1379 	while((name = strchr(old_name, sep)) != NULL) {
1380 		if (name - old_name > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
1381 			mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1382 				"Mailbox name too long");
1383 			return -1;
1384 		}
1385 		name++;
1386 		old_name = name;
1387 	}
1388 	if (strlen(old_name) > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
1389 		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1390 				       "Mailbox name too long");
1391 		return -1;
1392 	}
1393 	return 0;
1394 }
1395 
have_listable_namespace_prefix(struct mail_namespace * ns,const char * name)1396 static bool have_listable_namespace_prefix(struct mail_namespace *ns,
1397 					   const char *name)
1398 {
1399 	size_t name_len = strlen(name);
1400 
1401 	for (; ns != NULL; ns = ns->next) {
1402 		if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
1403 				  NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
1404 			continue;
1405 
1406 		if (ns->prefix_len <= name_len)
1407 			continue;
1408 
1409 		/* if prefix has multiple hierarchies, match
1410 		   any of the hierarchies */
1411 		if (strncmp(ns->prefix, name, name_len) == 0 &&
1412 		    ns->prefix[name_len] == mail_namespace_get_sep(ns))
1413 			return TRUE;
1414 	}
1415 	return FALSE;
1416 }
1417 
mailbox_exists(struct mailbox * box,bool auto_boxes,enum mailbox_existence * existence_r)1418 int mailbox_exists(struct mailbox *box, bool auto_boxes,
1419 		   enum mailbox_existence *existence_r)
1420 {
1421 	switch (box->open_error) {
1422 	case 0:
1423 		break;
1424 	case MAIL_ERROR_NOTFOUND:
1425 		*existence_r = MAILBOX_EXISTENCE_NONE;
1426 		return 0;
1427 	default:
1428 		/* unsure if this exists or not */
1429 		return -1;
1430 	}
1431 	if (mailbox_verify_name(box) < 0) {
1432 		/* the mailbox name is invalid. we don't know if it currently
1433 		   exists or not, but since it can never be accessed in any way
1434 		   report it as if it didn't exist. */
1435 		*existence_r = MAILBOX_EXISTENCE_NONE;
1436 		return 0;
1437 	}
1438 
1439 	if (box->v.exists(box, auto_boxes, existence_r) < 0)
1440 		return -1;
1441 
1442 	if (!box->inbox_user && *existence_r == MAILBOX_EXISTENCE_NOSELECT &&
1443 	    have_listable_namespace_prefix(box->storage->user->namespaces,
1444 					   box->vname)) {
1445 	       /* listable namespace prefix always exists. */
1446 		*existence_r = MAILBOX_EXISTENCE_NOSELECT;
1447 		return 0;
1448 	}
1449 
1450 	/* if this is a shared namespace with only INBOX and
1451 	   mail_shared_explicit_inbox=no, we'll need to mark the namespace as
1452 	   usable here since nothing else will. */
1453 	box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
1454 	return 0;
1455 }
1456 
1457 static int ATTR_NULL(2)
mailbox_open_full(struct mailbox * box,struct istream * input)1458 mailbox_open_full(struct mailbox *box, struct istream *input)
1459 {
1460 	int ret;
1461 
1462 	if (box->opened)
1463 		return 0;
1464 
1465 	if (box->reason != NULL) {
1466 		e_debug(box->event,
1467 			"Mailbox opened because: %s",
1468 			box->reason);
1469 	}
1470 
1471 	switch (box->open_error) {
1472 	case 0:
1473 		break;
1474 	case MAIL_ERROR_NOTFOUND:
1475 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
1476 			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
1477 		return -1;
1478 	default:
1479 		mail_storage_set_internal_error(box->storage);
1480 		box->storage->error = box->open_error;
1481 		return -1;
1482 	}
1483 
1484 	if (mailbox_verify_existing_name(box) < 0)
1485 		return -1;
1486 
1487 	if (input != NULL) {
1488 		if ((box->storage->class_flags &
1489 		     MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS) == 0) {
1490 			mailbox_set_critical(box,
1491 				"Storage doesn't support streamed mailboxes");
1492 			return -1;
1493 		}
1494 		box->input = input;
1495 		box->flags |= MAILBOX_FLAG_READONLY;
1496 		i_stream_ref(box->input);
1497 	}
1498 
1499 	T_BEGIN {
1500 		ret = box->v.open(box);
1501 	} T_END;
1502 
1503 	if (ret < 0 && box->storage->error == MAIL_ERROR_NOTFOUND &&
1504 	    !box->deleting && !box->creating &&
1505 	    box->input == NULL && mailbox_is_autocreated(box)) T_BEGIN {
1506 		ret = mailbox_autocreate_and_reopen(box);
1507 	} T_END;
1508 
1509 	if (ret < 0) {
1510 		if (box->input != NULL)
1511 			i_stream_unref(&box->input);
1512 		return -1;
1513 	}
1514 
1515 	box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
1516 	return 0;
1517 }
1518 
mailbox_try_undelete(struct mailbox * box)1519 static bool mailbox_try_undelete(struct mailbox *box)
1520 {
1521 	time_t mtime;
1522 
1523 	i_assert(!box->mailbox_undeleting);
1524 
1525 	if ((box->flags & MAILBOX_FLAG_READONLY) != 0) {
1526 		/* most importantly we don't do this because we want to avoid
1527 		   a loop: mdbox storage rebuild -> mailbox_open() ->
1528 		   mailbox_mark_index_deleted() -> mailbox_sync() ->
1529 		   mdbox storage rebuild. */
1530 		return FALSE;
1531 	}
1532 	if (mail_index_get_modification_time(box->index, &mtime) < 0)
1533 		return FALSE;
1534 	if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL))
1535 		return FALSE;
1536 
1537 	box->mailbox_undeleting = TRUE;
1538 	int ret = mailbox_mark_index_deleted(box, FALSE);
1539 	box->mailbox_undeleting = FALSE;
1540 	if (ret < 0)
1541 		return FALSE;
1542 	box->mailbox_deleted = FALSE;
1543 	return TRUE;
1544 }
1545 
mailbox_open(struct mailbox * box)1546 int mailbox_open(struct mailbox *box)
1547 {
1548 	if (mailbox_open_full(box, NULL) < 0) {
1549 		if (!box->mailbox_deleted || box->mailbox_undeleting)
1550 			return -1;
1551 
1552 		/* mailbox has been marked as deleted. if this deletion
1553 		   started (and crashed) a long time ago, it can be confusing
1554 		   to user that the mailbox can't be opened. so we'll just
1555 		   undelete it and reopen. */
1556 		if(!mailbox_try_undelete(box))
1557 			return -1;
1558 
1559 		/* make sure we close the mailbox in the middle. some backends
1560 		   may not have fully opened the mailbox while it was being
1561 		   undeleted. */
1562 		mailbox_close(box);
1563 		if (mailbox_open_full(box, NULL) < 0)
1564 			return -1;
1565 	}
1566 	return 0;
1567 }
1568 
mailbox_alloc_index_pvt(struct mailbox * box)1569 static int mailbox_alloc_index_pvt(struct mailbox *box)
1570 {
1571 	const char *index_dir;
1572 	int ret;
1573 
1574 	if (box->index_pvt != NULL)
1575 		return 1;
1576 
1577 	ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE,
1578 				  &index_dir);
1579 	if (ret <= 0)
1580 		return ret; /* error / no private indexes */
1581 
1582 	if (mailbox_create_missing_dir(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE) < 0)
1583 		return -1;
1584 
1585 	/* Note that this may cause box->event to live longer than box */
1586 	box->index_pvt = mail_index_alloc_cache_get(box->event,
1587 		NULL, index_dir, t_strconcat(box->index_prefix, ".pvt", NULL));
1588 	mail_index_set_fsync_mode(box->index_pvt,
1589 				  box->storage->set->parsed_fsync_mode, 0);
1590 	mail_index_set_lock_method(box->index_pvt,
1591 		box->storage->set->parsed_lock_method,
1592 		mail_storage_get_lock_timeout(box->storage, UINT_MAX));
1593 	return 1;
1594 }
1595 
mailbox_open_index_pvt(struct mailbox * box)1596 int mailbox_open_index_pvt(struct mailbox *box)
1597 {
1598 	enum mail_index_open_flags index_flags;
1599 	int ret;
1600 
1601 	if (box->view_pvt != NULL)
1602 		return 1;
1603 	if (mailbox_get_private_flags_mask(box) == 0)
1604 		return 0;
1605 
1606 	if ((ret = mailbox_alloc_index_pvt(box)) <= 0)
1607 		return ret;
1608 	index_flags = MAIL_INDEX_OPEN_FLAG_CREATE |
1609 		mail_storage_settings_to_index_flags(box->storage->set);
1610 	if ((box->flags & MAILBOX_FLAG_SAVEONLY) != 0)
1611 		index_flags |= MAIL_INDEX_OPEN_FLAG_SAVEONLY;
1612 	if (mail_index_open(box->index_pvt, index_flags) < 0)
1613 		return -1;
1614 	box->view_pvt = mail_index_view_open(box->index_pvt);
1615 	return 1;
1616 }
1617 
mailbox_open_stream(struct mailbox * box,struct istream * input)1618 int mailbox_open_stream(struct mailbox *box, struct istream *input)
1619 {
1620 	return mailbox_open_full(box, input);
1621 }
1622 
mailbox_enable(struct mailbox * box,enum mailbox_feature features)1623 int mailbox_enable(struct mailbox *box, enum mailbox_feature features)
1624 {
1625 	if (mailbox_verify_name(box) < 0)
1626 		return -1;
1627 	return box->v.enable(box, features);
1628 }
1629 
mailbox_get_enabled_features(struct mailbox * box)1630 enum mailbox_feature mailbox_get_enabled_features(struct mailbox *box)
1631 {
1632 	return box->enabled_features;
1633 }
1634 
mail_storage_free_binary_cache(struct mail_storage * storage)1635 void mail_storage_free_binary_cache(struct mail_storage *storage)
1636 {
1637 	if (storage->binary_cache.box == NULL)
1638 		return;
1639 
1640 	timeout_remove(&storage->binary_cache.to);
1641 	i_stream_destroy(&storage->binary_cache.input);
1642 	i_zero(&storage->binary_cache);
1643 }
1644 
mailbox_close(struct mailbox * box)1645 void mailbox_close(struct mailbox *box)
1646 {
1647 	if (!box->opened)
1648 		return;
1649 
1650 	if (box->transaction_count != 0) {
1651 		i_panic("Trying to close mailbox %s with open transactions",
1652 			box->name);
1653 	}
1654 	box->v.close(box);
1655 
1656 	if (box->storage->binary_cache.box == box)
1657 		mail_storage_free_binary_cache(box->storage);
1658 	box->opened = FALSE;
1659 	box->mailbox_deleted = FALSE;
1660 	array_clear(&box->search_results);
1661 
1662 	if (array_is_created(&box->recent_flags))
1663 		array_free(&box->recent_flags);
1664 	box->recent_flags_prev_uid = 0;
1665 	box->recent_flags_count = 0;
1666 }
1667 
mailbox_free(struct mailbox ** _box)1668 void mailbox_free(struct mailbox **_box)
1669 {
1670 	struct mailbox *box = *_box;
1671 
1672 	*_box = NULL;
1673 
1674 	mailbox_close(box);
1675 	box->v.free(box);
1676 
1677 	if (box->attribute_iter_count != 0) {
1678 		i_panic("Trying to free mailbox %s with %u open attribute iterators",
1679 			box->name, box->attribute_iter_count);
1680 	}
1681 
1682 	DLLIST_REMOVE(&box->storage->mailboxes, box);
1683 	mail_storage_obj_unref(box->storage);
1684 	pool_unref(&box->pool);
1685 }
1686 
mailbox_equals(const struct mailbox * box1,const struct mail_namespace * ns2,const char * vname2)1687 bool mailbox_equals(const struct mailbox *box1,
1688 		    const struct mail_namespace *ns2, const char *vname2)
1689 {
1690 	struct mail_namespace *ns1 = mailbox_get_namespace(box1);
1691 	const char *name1;
1692 
1693 	if (ns1 != ns2)
1694 		return FALSE;
1695 
1696         name1 = mailbox_get_vname(box1);
1697 	if (strcmp(name1, vname2) == 0)
1698 		return TRUE;
1699 
1700 	return strcasecmp(name1, "INBOX") == 0 &&
1701 		strcasecmp(vname2, "INBOX") == 0;
1702 }
1703 
mailbox_is_any_inbox(struct mailbox * box)1704 bool mailbox_is_any_inbox(struct mailbox *box)
1705 {
1706 	return box->inbox_any;
1707 }
1708 
mailbox_has_special_use(struct mailbox * box,const char * special_use)1709 bool mailbox_has_special_use(struct mailbox *box, const char *special_use)
1710 {
1711 	if (box->set == NULL)
1712 		return FALSE;
1713 	return str_contains_special_use(box->set->special_use, special_use);
1714 }
1715 
mailbox_copy_cache_decisions_from_inbox(struct mailbox * box)1716 static void mailbox_copy_cache_decisions_from_inbox(struct mailbox *box)
1717 {
1718 	struct mail_namespace *ns =
1719 		mail_namespace_find_inbox(box->storage->user->namespaces);
1720 	struct mailbox *inbox =
1721 		mailbox_alloc(ns->list, "INBOX", MAILBOX_FLAG_READONLY);
1722 	enum mailbox_existence existence;
1723 
1724 	/* this should be NoSelect but since inbox can never be
1725 	   NoSelect we use EXISTENCE_NONE to avoid creating inbox by accident */
1726 	mailbox_set_reason(inbox, "copy caching decisions");
1727 	if (mailbox_exists(inbox, FALSE, &existence) == 0 &&
1728 	    existence != MAILBOX_EXISTENCE_NONE &&
1729 	    mailbox_open(inbox) == 0 &&
1730 	    mailbox_open(box) == 0) {
1731 		/* we can't do much about errors here */
1732 		(void)mail_cache_decisions_copy(inbox->cache, box->cache);
1733 	}
1734 
1735 	mailbox_free(&inbox);
1736 }
1737 
mailbox_create(struct mailbox * box,const struct mailbox_update * update,bool directory)1738 int mailbox_create(struct mailbox *box, const struct mailbox_update *update,
1739 		   bool directory)
1740 {
1741 	int ret;
1742 
1743 	if (mailbox_verify_create_name(box) < 0)
1744 		return -1;
1745 
1746 	/* Avoid race conditions by keeping mailbox list locked during changes.
1747 	   This especially fixes a race during INBOX creation with LAYOUT=index
1748 	   because it scans for missing mailboxes if INBOX doesn't exist. The
1749 	   second process's scan can find a half-created INBOX and add it,
1750 	   causing the first process to become confused. */
1751 	if (mailbox_list_lock(box->list) < 0) {
1752 		mail_storage_copy_list_error(box->storage, box->list);
1753 		return -1;
1754 	}
1755 	box->creating = TRUE;
1756 	T_BEGIN {
1757 		ret = box->v.create_box(box, update, directory);
1758 	} T_END;
1759 	box->creating = FALSE;
1760 	mailbox_list_unlock(box->list);
1761 
1762 	if (ret == 0) {
1763 		box->list->guid_cache_updated = TRUE;
1764 		if (!box->inbox_any) T_BEGIN {
1765 			mailbox_copy_cache_decisions_from_inbox(box);
1766 		} T_END;
1767 	} else if (box->opened) {
1768 		/* Creation failed after (partially) opening the mailbox.
1769 		   It may not be in a valid state, so close it. */
1770 		mail_storage_last_error_push(box->storage);
1771 		mailbox_close(box);
1772 		mail_storage_last_error_pop(box->storage);
1773 	}
1774 	return ret;
1775 }
1776 
mailbox_update(struct mailbox * box,const struct mailbox_update * update)1777 int mailbox_update(struct mailbox *box, const struct mailbox_update *update)
1778 {
1779 	int ret;
1780 
1781 	i_assert(update->min_next_uid == 0 ||
1782 		 update->min_first_recent_uid == 0 ||
1783 		 update->min_first_recent_uid <= update->min_next_uid);
1784 
1785 	if (mailbox_verify_existing_name(box) < 0)
1786 		return -1;
1787 	ret = box->v.update_box(box, update);
1788 	if (!guid_128_is_empty(update->mailbox_guid))
1789 		box->list->guid_cache_invalidated = TRUE;
1790 	return ret;
1791 }
1792 
mailbox_mark_index_deleted(struct mailbox * box,bool del)1793 int mailbox_mark_index_deleted(struct mailbox *box, bool del)
1794 {
1795 	struct mail_index_transaction *trans;
1796 	enum mail_index_transaction_flags trans_flags = 0;
1797 	enum mailbox_flags old_flag;
1798 	int ret;
1799 
1800 	e_debug(box->event, "Attempting to %s mailbox", del ?
1801 		"delete" : "undelete");
1802 
1803 	if (box->marked_deleted && del) {
1804 		/* we already marked it deleted. this allows plugins to
1805 		   "lock" the deletion earlier. */
1806 		return 0;
1807 	}
1808 
1809 	old_flag = box->flags & MAILBOX_FLAG_OPEN_DELETED;
1810 	box->flags |= MAILBOX_FLAG_OPEN_DELETED;
1811 	ret = mailbox_open(box);
1812 	box->flags = (box->flags & ENUM_NEGATE(MAILBOX_FLAG_OPEN_DELETED)) | old_flag;
1813 	if (ret < 0)
1814 		return -1;
1815 
1816 	trans_flags = del ? 0 : MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
1817 	trans = mail_index_transaction_begin(box->view, trans_flags);
1818 	if (del)
1819 		mail_index_set_deleted(trans);
1820 	else
1821 		mail_index_set_undeleted(trans);
1822 	if (mail_index_transaction_commit(&trans) < 0) {
1823 		mailbox_set_index_error(box);
1824 		return -1;
1825 	}
1826 
1827 	if (del) {
1828 		/* sync the mailbox. this finishes the index deletion and it
1829 		   can succeed only for a single session. we do it here, so the
1830 		   rest of the deletion code doesn't have to worry about race
1831 		   conditions. */
1832 		box->delete_sync_check = TRUE;
1833 		ret = mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ);
1834 		box->delete_sync_check = FALSE;
1835 		if (ret < 0)
1836 			return -1;
1837 	}
1838 
1839 	box->marked_deleted = del;
1840 	return 0;
1841 }
1842 
mailbox_close_reset_path(struct mailbox * box)1843 static void mailbox_close_reset_path(struct mailbox *box)
1844 {
1845 	i_zero(&box->_perm);
1846 	box->_path = NULL;
1847 	box->_index_path = NULL;
1848 }
1849 
mailbox_delete_real(struct mailbox * box)1850 static int mailbox_delete_real(struct mailbox *box)
1851 {
1852 	bool list_locked;
1853 	int ret;
1854 
1855 	if (*box->name == '\0') {
1856 		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1857 				       "Storage root can't be deleted");
1858 		return -1;
1859 	}
1860 
1861 	box->deleting = TRUE;
1862 	if (mailbox_open(box) < 0) {
1863 		if (mailbox_get_last_mail_error(box) != MAIL_ERROR_NOTFOUND &&
1864 		    !box->mailbox_deleted)
1865 			return -1;
1866 		/* might be a \noselect mailbox, so continue deletion */
1867 	}
1868 
1869 	if (mailbox_list_lock(box->list) < 0) {
1870 		mail_storage_copy_list_error(box->storage, box->list);
1871 		list_locked = FALSE;
1872 		ret = -1;
1873 	} else {
1874 		list_locked = TRUE;
1875 		ret = box->v.delete_box(box);
1876 	}
1877 	if (ret < 0 && box->marked_deleted) {
1878 		/* deletion failed. revert the mark so it can maybe be
1879 		   tried again later. */
1880 		if (mailbox_mark_index_deleted(box, FALSE) < 0)
1881 			ret = -1;
1882 	}
1883 	if (list_locked)
1884 		mailbox_list_unlock(box->list);
1885 
1886 	box->deleting = FALSE;
1887 	mailbox_close(box);
1888 
1889 	/* if mailbox is reopened, its path may be different with
1890 	   LAYOUT=index */
1891 	mailbox_close_reset_path(box);
1892 	return ret;
1893 }
1894 
mailbox_delete(struct mailbox * box)1895 int mailbox_delete(struct mailbox *box)
1896 {
1897 	int ret;
1898 	T_BEGIN {
1899 		ret = mailbox_delete_real(box);
1900 	} T_END;
1901 	return ret;
1902 }
1903 
mailbox_delete_empty(struct mailbox * box)1904 int mailbox_delete_empty(struct mailbox *box)
1905 {
1906 	int ret;
1907 
1908 	/* FIXME: should be a parameter to delete(), but since it changes API
1909 	   don't do it for now */
1910 	box->deleting_must_be_empty = TRUE;
1911 	ret = mailbox_delete(box);
1912 	box->deleting_must_be_empty = FALSE;
1913 	return ret;
1914 }
1915 
1916 static bool
mail_storages_rename_compatible(struct mail_storage * storage1,struct mail_storage * storage2,const char ** error_r)1917 mail_storages_rename_compatible(struct mail_storage *storage1,
1918 				struct mail_storage *storage2,
1919 				const char **error_r)
1920 {
1921 	if (storage1 == storage2)
1922 		return TRUE;
1923 
1924 	if (strcmp(storage1->name, storage2->name) != 0) {
1925 		*error_r = t_strdup_printf("storage %s != %s",
1926 					   storage1->name, storage2->name);
1927 		return FALSE;
1928 	}
1929 	if ((storage1->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0) {
1930 		/* e.g. mdbox where all mails are in storage/ directory and
1931 		   they can't be easily moved from there. */
1932 		*error_r = t_strdup_printf("storage %s uses unique root",
1933 					   storage1->name);
1934 		return FALSE;
1935 	}
1936 	return TRUE;
1937 }
1938 
nullequals(const void * p1,const void * p2)1939 static bool nullequals(const void *p1, const void *p2)
1940 {
1941 	return (p1 == NULL && p2 == NULL) || (p1 != NULL && p2 != NULL);
1942 }
1943 
1944 static bool
mailbox_lists_rename_compatible(struct mailbox_list * list1,struct mailbox_list * list2,const char ** error_r)1945 mailbox_lists_rename_compatible(struct mailbox_list *list1,
1946 				struct mailbox_list *list2,
1947 				const char **error_r)
1948 {
1949 	if (!nullequals(list1->set.alt_dir, list2->set.alt_dir)) {
1950 		*error_r = t_strdup_printf("Namespace %s has alt dir, %s doesn't",
1951 					   list1->ns->prefix, list2->ns->prefix);
1952 		return FALSE;
1953 	}
1954 	if (!nullequals(list1->set.index_dir, list2->set.index_dir)) {
1955 		*error_r = t_strdup_printf("Namespace %s has index dir, %s doesn't",
1956 					   list1->ns->prefix, list2->ns->prefix);
1957 		return FALSE;
1958 	}
1959 	if (!nullequals(list1->set.index_cache_dir, list2->set.index_cache_dir)) {
1960 		*error_r = t_strdup_printf("Namespace %s has index cache dir, %s doesn't",
1961 					   list1->ns->prefix, list2->ns->prefix);
1962 		return FALSE;
1963 	}
1964 	if (!nullequals(list1->set.control_dir, list2->set.control_dir)) {
1965 		*error_r = t_strdup_printf("Namespace %s has control dir, %s doesn't",
1966 					   list1->ns->prefix, list2->ns->prefix);
1967 		return FALSE;
1968 	}
1969 	return TRUE;
1970 }
1971 
1972 static
mailbox_rename_check_children(struct mailbox * src,struct mailbox * dest)1973 int mailbox_rename_check_children(struct mailbox *src, struct mailbox *dest)
1974 {
1975 	int ret = 0;
1976 	size_t src_prefix_len = strlen(src->vname)+1; /* include separator */
1977 	size_t dest_prefix_len = strlen(dest->vname)+1;
1978 	/* this can return folders with * in their name, that are not
1979 	   actually our children */
1980 	char ns_sep = mail_namespace_get_sep(src->list->ns);
1981 	const char *pattern = t_strdup_printf("%s%c*", src->vname, ns_sep);
1982 
1983 	struct mailbox_list_iterate_context *iter = mailbox_list_iter_init(src->list, pattern,
1984 				      MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
1985 
1986 	const struct mailbox_info *child;
1987 	while((child = mailbox_list_iter_next(iter)) != NULL) {
1988 		if (strncmp(child->vname, src->vname, src_prefix_len-1) != 0 ||
1989 		    child->vname[src_prefix_len-1] != ns_sep)
1990 			continue; /* not our child */
1991 		/* if total length of new name exceeds the limit, fail */
1992 		if (strlen(child->vname + src_prefix_len)+dest_prefix_len > MAILBOX_LIST_NAME_MAX_LENGTH) {
1993 			mail_storage_set_error(src->storage, MAIL_ERROR_PARAMS,
1994 				"Mailbox or child name too long");
1995 			ret = -1;
1996 			break;
1997 		}
1998 	}
1999 
2000 	/* something went bad */
2001 	if (mailbox_list_iter_deinit(&iter) < 0) {
2002 		mail_storage_copy_list_error(src->storage, src->list);
2003 		ret = -1;
2004 	}
2005 	return ret;
2006 }
2007 
mailbox_rename_real(struct mailbox * src,struct mailbox * dest)2008 static int mailbox_rename_real(struct mailbox *src, struct mailbox *dest)
2009 {
2010 	const char *error = NULL;
2011 
2012 	/* Check only name validity, \Noselect don't necessarily exist. */
2013 	if (mailbox_verify_name(src) < 0)
2014 		return -1;
2015 	if (*src->name == '\0') {
2016 		mail_storage_set_error(src->storage, MAIL_ERROR_PARAMS,
2017 				       "Can't rename mailbox root");
2018 		return -1;
2019 	}
2020 	if (mailbox_verify_create_name(dest) < 0) {
2021 		mail_storage_copy_error(src->storage, dest->storage);
2022 		return -1;
2023 	}
2024 	if (mailbox_rename_check_children(src, dest) != 0) {
2025 		return -1;
2026 	}
2027 
2028 	if (!mail_storages_rename_compatible(src->storage,
2029 					     dest->storage, &error) ||
2030 	    !mailbox_lists_rename_compatible(src->list,
2031 					     dest->list, &error)) {
2032 		e_debug(src->event,
2033 			"Can't rename '%s' to '%s': %s",
2034 			src->vname, dest->vname, error);
2035 		mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
2036 			"Can't rename mailboxes across specified storages.");
2037 		return -1;
2038 	}
2039 	if (src->list != dest->list &&
2040 	    (src->list->ns->type != MAIL_NAMESPACE_TYPE_PRIVATE ||
2041 	     dest->list->ns->type != MAIL_NAMESPACE_TYPE_PRIVATE)) {
2042 		mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
2043 			"Renaming not supported across non-private namespaces.");
2044 		return -1;
2045 	}
2046 	if (src->list == dest->list && strcmp(src->name, dest->name) == 0) {
2047 		mail_storage_set_error(src->storage, MAIL_ERROR_EXISTS,
2048 				       "Can't rename mailbox to itself.");
2049 		return -1;
2050 	}
2051 
2052 	/* It would be safer to lock both source and destination, but that
2053 	   could lead to deadlocks. So at least for now lets just lock only the
2054 	   destination list. */
2055 	if (mailbox_list_lock(dest->list) < 0) {
2056 		mail_storage_copy_list_error(src->storage, dest->list);
2057 		return -1;
2058 	}
2059 	int ret = src->v.rename_box(src, dest);
2060 	mailbox_list_unlock(dest->list);
2061 	if (ret < 0)
2062 		return -1;
2063 	src->list->guid_cache_invalidated = TRUE;
2064 	dest->list->guid_cache_invalidated = TRUE;
2065 	return 0;
2066 }
2067 
mailbox_rename(struct mailbox * src,struct mailbox * dest)2068 int mailbox_rename(struct mailbox *src, struct mailbox *dest)
2069 {
2070 	 int ret;
2071 	 T_BEGIN {
2072 		 ret = mailbox_rename_real(src, dest);
2073 	 } T_END;
2074 	 return ret;
2075 }
2076 
mailbox_set_subscribed(struct mailbox * box,bool set)2077 int mailbox_set_subscribed(struct mailbox *box, bool set)
2078 {
2079 	if (mailbox_verify_name(box) < 0)
2080 		return -1;
2081 	if (mailbox_list_iter_subscriptions_refresh(box->list) < 0) {
2082 		mail_storage_copy_list_error(box->storage, box->list);
2083 		return -1;
2084 	}
2085 	if (mailbox_is_subscribed(box) == set)
2086 		return 0;
2087 	return box->v.set_subscribed(box, set);
2088 }
2089 
mailbox_is_subscribed(struct mailbox * box)2090 bool mailbox_is_subscribed(struct mailbox *box)
2091 {
2092 	struct mailbox_node *node;
2093 
2094 	i_assert(box->list->subscriptions != NULL);
2095 
2096 	node = mailbox_tree_lookup(box->list->subscriptions, box->vname);
2097 	return node != NULL && (node->flags & MAILBOX_SUBSCRIBED) != 0;
2098 }
2099 
mailbox_get_storage(const struct mailbox * box)2100 struct mail_storage *mailbox_get_storage(const struct mailbox *box)
2101 {
2102 	return box->storage;
2103 }
2104 
2105 struct mail_namespace *
mailbox_get_namespace(const struct mailbox * box)2106 mailbox_get_namespace(const struct mailbox *box)
2107 {
2108 	return box->list->ns;
2109 }
2110 
mailbox_get_settings(struct mailbox * box)2111 const struct mail_storage_settings *mailbox_get_settings(struct mailbox *box)
2112 {
2113 	return box->storage->set;
2114 }
2115 
mailbox_get_name(const struct mailbox * box)2116 const char *mailbox_get_name(const struct mailbox *box)
2117 {
2118 	return box->name;
2119 }
2120 
mailbox_get_vname(const struct mailbox * box)2121 const char *mailbox_get_vname(const struct mailbox *box)
2122 {
2123 	return box->vname;
2124 }
2125 
mailbox_is_readonly(struct mailbox * box)2126 bool mailbox_is_readonly(struct mailbox *box)
2127 {
2128 	i_assert(box->opened);
2129 
2130 	return box->v.is_readonly(box);
2131 }
2132 
mailbox_backends_equal(const struct mailbox * box1,const struct mailbox * box2)2133 bool mailbox_backends_equal(const struct mailbox *box1,
2134 			    const struct mailbox *box2)
2135 {
2136 	struct mail_namespace *ns1 = box1->list->ns, *ns2 = box2->list->ns;
2137 
2138 	if (strcmp(box1->name, box2->name) != 0)
2139 		return FALSE;
2140 
2141 	while (ns1->alias_for != NULL)
2142 		ns1 = ns1->alias_for;
2143 	while (ns2->alias_for != NULL)
2144 		ns2 = ns2->alias_for;
2145 	return ns1 == ns2;
2146 }
2147 
2148 static void
mailbox_get_status_set_defaults(struct mailbox * box,struct mailbox_status * status_r)2149 mailbox_get_status_set_defaults(struct mailbox *box,
2150 				struct mailbox_status *status_r)
2151 {
2152 	i_zero(status_r);
2153 	if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUIDS) != 0)
2154 		status_r->have_guids = TRUE;
2155 	if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS) != 0)
2156 		status_r->have_save_guids = TRUE;
2157 	if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUID128) != 0)
2158 		status_r->have_only_guid128 = TRUE;
2159 }
2160 
mailbox_get_status(struct mailbox * box,enum mailbox_status_items items,struct mailbox_status * status_r)2161 int mailbox_get_status(struct mailbox *box,
2162 		       enum mailbox_status_items items,
2163 		       struct mailbox_status *status_r)
2164 {
2165 	mailbox_get_status_set_defaults(box, status_r);
2166 	if (mailbox_verify_existing_name(box) < 0)
2167 		return -1;
2168 
2169 	if (box->v.get_status(box, items, status_r) < 0)
2170 		return -1;
2171 	i_assert(status_r->have_guids || !status_r->have_save_guids);
2172 	return 0;
2173 }
2174 
mailbox_get_open_status(struct mailbox * box,enum mailbox_status_items items,struct mailbox_status * status_r)2175 void mailbox_get_open_status(struct mailbox *box,
2176 			     enum mailbox_status_items items,
2177 			     struct mailbox_status *status_r)
2178 {
2179 	i_assert(box->opened);
2180 	i_assert((items & MAILBOX_STATUS_FAILING_ITEMS) == 0);
2181 
2182 	mailbox_get_status_set_defaults(box, status_r);
2183 	if (box->v.get_status(box, items, status_r) < 0)
2184 		i_unreached();
2185 }
2186 
mailbox_get_metadata(struct mailbox * box,enum mailbox_metadata_items items,struct mailbox_metadata * metadata_r)2187 int mailbox_get_metadata(struct mailbox *box, enum mailbox_metadata_items items,
2188 			 struct mailbox_metadata *metadata_r)
2189 {
2190 	i_zero(metadata_r);
2191 	if (mailbox_verify_existing_name(box) < 0)
2192 		return -1;
2193 
2194 	if (box->v.get_metadata(box, items, metadata_r) < 0)
2195 		return -1;
2196 
2197 	i_assert((items & MAILBOX_METADATA_GUID) == 0 ||
2198 		 !guid_128_is_empty(metadata_r->guid));
2199 	return 0;
2200 }
2201 
mailbox_get_private_flags_mask(struct mailbox * box)2202 enum mail_flags mailbox_get_private_flags_mask(struct mailbox *box)
2203 {
2204 	if (box->v.get_private_flags_mask != NULL)
2205 		return box->v.get_private_flags_mask(box);
2206 	else if (box->list->set.index_pvt_dir != NULL)
2207 		return MAIL_SEEN; /* FIXME */
2208 	else
2209 		return 0;
2210 }
2211 
2212 struct mailbox_sync_context *
mailbox_sync_init(struct mailbox * box,enum mailbox_sync_flags flags)2213 mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
2214 {
2215 	struct mailbox_sync_context *ctx;
2216 
2217 	if (box->transaction_count != 0) {
2218 		i_panic("Trying to sync mailbox %s with open transactions",
2219 			box->name);
2220 	}
2221 	if (!box->opened) {
2222 		if (mailbox_open(box) < 0) {
2223 			ctx = i_new(struct mailbox_sync_context, 1);
2224 			ctx->box = box;
2225 			ctx->flags = flags;
2226 			ctx->open_failed = TRUE;
2227 			return ctx;
2228 		}
2229 	}
2230 	T_BEGIN {
2231 		ctx = box->v.sync_init(box, flags);
2232 	} T_END;
2233 	return ctx;
2234 }
2235 
mailbox_sync_next(struct mailbox_sync_context * ctx,struct mailbox_sync_rec * sync_rec_r)2236 bool mailbox_sync_next(struct mailbox_sync_context *ctx,
2237 		       struct mailbox_sync_rec *sync_rec_r)
2238 {
2239 	if (ctx->open_failed)
2240 		return FALSE;
2241 	return ctx->box->v.sync_next(ctx, sync_rec_r);
2242 }
2243 
mailbox_sync_deinit(struct mailbox_sync_context ** _ctx,struct mailbox_sync_status * status_r)2244 int mailbox_sync_deinit(struct mailbox_sync_context **_ctx,
2245 			struct mailbox_sync_status *status_r)
2246 {
2247 	struct mailbox_sync_context *ctx = *_ctx;
2248 	struct mailbox *box = ctx->box;
2249 	const char *errormsg;
2250 	enum mail_error error;
2251 	int ret;
2252 
2253 	*_ctx = NULL;
2254 
2255 	i_zero(status_r);
2256 
2257 	if (!ctx->open_failed)
2258 		ret = box->v.sync_deinit(ctx, status_r);
2259 	else {
2260 		i_free(ctx);
2261 		ret = -1;
2262 	}
2263 	if (ret < 0 && box->inbox_user &&
2264 	    !box->storage->user->inbox_open_error_logged) {
2265 		errormsg = mailbox_get_last_internal_error(box, &error);
2266 		if (error == MAIL_ERROR_NOTPOSSIBLE) {
2267 			box->storage->user->inbox_open_error_logged = TRUE;
2268 			e_error(box->event, "Syncing INBOX failed: %s", errormsg);
2269 		}
2270 	}
2271 	if (ret == 0)
2272 		box->synced = TRUE;
2273 	return ret;
2274 }
2275 
mailbox_sync(struct mailbox * box,enum mailbox_sync_flags flags)2276 int mailbox_sync(struct mailbox *box, enum mailbox_sync_flags flags)
2277 {
2278 	struct mailbox_sync_context *ctx;
2279 	struct mailbox_sync_status status;
2280 
2281 	if (array_count(&box->search_results) == 0) {
2282 		/* we don't care about mailbox's current state, so we might
2283 		   as well fix inconsistency state */
2284 		flags |= MAILBOX_SYNC_FLAG_FIX_INCONSISTENT;
2285 	}
2286 
2287 	ctx = mailbox_sync_init(box, flags);
2288 	return mailbox_sync_deinit(&ctx, &status);
2289 }
2290 
2291 #undef mailbox_notify_changes
mailbox_notify_changes(struct mailbox * box,mailbox_notify_callback_t * callback,void * context)2292 void mailbox_notify_changes(struct mailbox *box,
2293 			    mailbox_notify_callback_t *callback, void *context)
2294 {
2295 	i_assert(box->opened);
2296 
2297 	box->notify_callback = callback;
2298 	box->notify_context = context;
2299 
2300 	box->v.notify_changes(box);
2301 }
2302 
mailbox_notify_changes_stop(struct mailbox * box)2303 void mailbox_notify_changes_stop(struct mailbox *box)
2304 {
2305 	i_assert(box->opened);
2306 
2307 	box->notify_callback = NULL;
2308 	box->notify_context = NULL;
2309 
2310 	box->v.notify_changes(box);
2311 }
2312 
2313 struct mail_search_context *
mailbox_search_init(struct mailbox_transaction_context * t,struct mail_search_args * args,const enum mail_sort_type * sort_program,enum mail_fetch_field wanted_fields,struct mailbox_header_lookup_ctx * wanted_headers)2314 mailbox_search_init(struct mailbox_transaction_context *t,
2315 		    struct mail_search_args *args,
2316 		    const enum mail_sort_type *sort_program,
2317 		    enum mail_fetch_field wanted_fields,
2318 		    struct mailbox_header_lookup_ctx *wanted_headers)
2319 {
2320 	i_assert(wanted_headers == NULL || wanted_headers->box == t->box);
2321 
2322 	mail_search_args_ref(args);
2323 	if (!args->simplified)
2324 		mail_search_args_simplify(args);
2325 	return t->box->v.search_init(t, args, sort_program,
2326 				     wanted_fields, wanted_headers);
2327 }
2328 
mailbox_search_deinit(struct mail_search_context ** _ctx)2329 int mailbox_search_deinit(struct mail_search_context **_ctx)
2330 {
2331 	struct mail_search_context *ctx = *_ctx;
2332 	struct mail_search_args *args = ctx->args;
2333 	int ret;
2334 
2335 	*_ctx = NULL;
2336 	mailbox_search_results_initial_done(ctx);
2337 	ret = ctx->transaction->box->v.search_deinit(ctx);
2338 	mail_search_args_unref(&args);
2339 	return ret;
2340 }
2341 
mailbox_search_next(struct mail_search_context * ctx,struct mail ** mail_r)2342 bool mailbox_search_next(struct mail_search_context *ctx, struct mail **mail_r)
2343 {
2344 	bool tryagain;
2345 
2346 	while (!mailbox_search_next_nonblock(ctx, mail_r, &tryagain)) {
2347 		if (!tryagain)
2348 			return FALSE;
2349 	}
2350 	return TRUE;
2351 }
2352 
mailbox_search_next_nonblock(struct mail_search_context * ctx,struct mail ** mail_r,bool * tryagain_r)2353 bool mailbox_search_next_nonblock(struct mail_search_context *ctx,
2354 				  struct mail **mail_r, bool *tryagain_r)
2355 {
2356 	struct mailbox *box = ctx->transaction->box;
2357 
2358 	*mail_r = NULL;
2359 	*tryagain_r = FALSE;
2360 
2361 	if (!box->v.search_next_nonblock(ctx, mail_r, tryagain_r))
2362 		return FALSE;
2363 	else {
2364 		mailbox_search_results_add(ctx, (*mail_r)->uid);
2365 		return TRUE;
2366 	}
2367 }
2368 
mailbox_search_seen_lost_data(struct mail_search_context * ctx)2369 bool mailbox_search_seen_lost_data(struct mail_search_context *ctx)
2370 {
2371 	return ctx->seen_lost_data;
2372 }
2373 
mailbox_search_mail_detach(struct mail_search_context * ctx,struct mail * mail)2374 void mailbox_search_mail_detach(struct mail_search_context *ctx,
2375 				struct mail *mail)
2376 {
2377 	struct mail_private *pmail =
2378 		container_of(mail, struct mail_private, mail);
2379 	struct mail *const *mailp;
2380 
2381 	array_foreach(&ctx->mails, mailp) {
2382 		if (*mailp == mail) {
2383 			pmail->search_mail = FALSE;
2384 			array_delete(&ctx->mails,
2385 				     array_foreach_idx(&ctx->mails, mailp), 1);
2386 			return;
2387 		}
2388 	}
2389 	i_unreached();
2390 }
2391 
mailbox_search_result_build(struct mailbox_transaction_context * t,struct mail_search_args * args,enum mailbox_search_result_flags flags,struct mail_search_result ** result_r)2392 int mailbox_search_result_build(struct mailbox_transaction_context *t,
2393 				struct mail_search_args *args,
2394 				enum mailbox_search_result_flags flags,
2395 				struct mail_search_result **result_r)
2396 {
2397 	struct mail_search_context *ctx;
2398 	struct mail *mail;
2399 	int ret;
2400 
2401 	ctx = mailbox_search_init(t, args, NULL, 0, NULL);
2402 	*result_r = mailbox_search_result_save(ctx, flags);
2403 	while (mailbox_search_next(ctx, &mail)) ;
2404 
2405 	ret = mailbox_search_deinit(&ctx);
2406 	if (ret < 0)
2407 		mailbox_search_result_free(result_r);
2408 	return ret;
2409 }
2410 
2411 struct mailbox_transaction_context *
mailbox_transaction_begin(struct mailbox * box,enum mailbox_transaction_flags flags,const char * reason)2412 mailbox_transaction_begin(struct mailbox *box,
2413 			  enum mailbox_transaction_flags flags,
2414 			  const char *reason)
2415 {
2416 	struct mailbox_transaction_context *trans;
2417 
2418 	i_assert(box->opened);
2419 
2420 	box->transaction_count++;
2421 	trans = box->v.transaction_begin(box, flags, reason);
2422 	i_assert(trans->reason != NULL);
2423 	return trans;
2424 }
2425 
mailbox_transaction_commit(struct mailbox_transaction_context ** t)2426 int mailbox_transaction_commit(struct mailbox_transaction_context **t)
2427 {
2428 	struct mail_transaction_commit_changes changes;
2429 	int ret;
2430 
2431 	/* Store changes temporarily so that plugins overriding
2432 	   transaction_commit() can look at them. */
2433 	ret = mailbox_transaction_commit_get_changes(t, &changes);
2434 	pool_unref(&changes.pool);
2435 	return ret;
2436 }
2437 
mailbox_transaction_commit_get_changes(struct mailbox_transaction_context ** _t,struct mail_transaction_commit_changes * changes_r)2438 int mailbox_transaction_commit_get_changes(
2439 	struct mailbox_transaction_context **_t,
2440 	struct mail_transaction_commit_changes *changes_r)
2441 {
2442 	struct mailbox_transaction_context *t = *_t;
2443 	struct mailbox *box = t->box;
2444 	unsigned int save_count = t->save_count;
2445 	int ret;
2446 
2447 	changes_r->pool = NULL;
2448 
2449 	*_t = NULL;
2450 	T_BEGIN {
2451 		ret = box->v.transaction_commit(t, changes_r);
2452 	} T_END;
2453 	/* either all the saved messages get UIDs or none, because a) we
2454 	   failed, b) MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS not set,
2455 	   c) backend doesn't support it (e.g. virtual plugin) */
2456 	i_assert(ret < 0 ||
2457 		 seq_range_count(&changes_r->saved_uids) == save_count ||
2458 		 array_count(&changes_r->saved_uids) == 0);
2459 	/* decrease the transaction count only after transaction_commit().
2460 	   that way if it creates and destroys transactions internally, we
2461 	   don't see transaction_count=0 until the parent transaction is fully
2462 	   finished */
2463 	box->transaction_count--;
2464 	if (ret < 0 && changes_r->pool != NULL)
2465 		pool_unref(&changes_r->pool);
2466 	return ret;
2467 }
2468 
mailbox_transaction_rollback(struct mailbox_transaction_context ** _t)2469 void mailbox_transaction_rollback(struct mailbox_transaction_context **_t)
2470 {
2471 	struct mailbox_transaction_context *t = *_t;
2472 	struct mailbox *box = t->box;
2473 
2474 	*_t = NULL;
2475 	box->v.transaction_rollback(t);
2476 	box->transaction_count--;
2477 }
2478 
mailbox_transaction_get_count(const struct mailbox * box)2479 unsigned int mailbox_transaction_get_count(const struct mailbox *box)
2480 {
2481 	return box->transaction_count;
2482 }
2483 
mailbox_transaction_set_max_modseq(struct mailbox_transaction_context * t,uint64_t max_modseq,ARRAY_TYPE (seq_range)* seqs)2484 void mailbox_transaction_set_max_modseq(struct mailbox_transaction_context *t,
2485 					uint64_t max_modseq,
2486 					ARRAY_TYPE(seq_range) *seqs)
2487 {
2488 	mail_index_transaction_set_max_modseq(t->itrans, max_modseq, seqs);
2489 }
2490 
2491 struct mailbox *
mailbox_transaction_get_mailbox(const struct mailbox_transaction_context * t)2492 mailbox_transaction_get_mailbox(const struct mailbox_transaction_context *t)
2493 {
2494 	return t->box;
2495 }
2496 
mailbox_save_dest_mail_close(struct mail_save_context * ctx)2497 static void mailbox_save_dest_mail_close(struct mail_save_context *ctx)
2498 {
2499 	struct mail_private *mail = (struct mail_private *)ctx->dest_mail;
2500 
2501 	mail->v.close(&mail->mail);
2502 }
2503 
2504 struct mail_save_context *
mailbox_save_alloc(struct mailbox_transaction_context * t)2505 mailbox_save_alloc(struct mailbox_transaction_context *t)
2506 {
2507 	struct mail_save_context *ctx;
2508 	T_BEGIN {
2509 		ctx = t->box->v.save_alloc(t);
2510 	} T_END;
2511 	i_assert(!ctx->unfinished);
2512 	ctx->unfinished = TRUE;
2513 	ctx->data.received_date = (time_t)-1;
2514 	ctx->data.save_date = (time_t)-1;
2515 
2516 	/* Always have a dest_mail available. A lot of plugins make use
2517 	   of this. */
2518 	if (ctx->dest_mail == NULL)
2519 		ctx->dest_mail = mail_alloc(t, 0, NULL);
2520 	else {
2521 		/* make sure the mail isn't used before mail_set_seq_saving() */
2522 		mailbox_save_dest_mail_close(ctx);
2523 	}
2524 
2525 	return ctx;
2526 }
2527 
mailbox_save_context_deinit(struct mail_save_context * ctx)2528 void mailbox_save_context_deinit(struct mail_save_context *ctx)
2529 {
2530 	i_assert(ctx->dest_mail != NULL);
2531 
2532 	mail_free(&ctx->dest_mail);
2533 }
2534 
mailbox_save_set_flags(struct mail_save_context * ctx,enum mail_flags flags,struct mail_keywords * keywords)2535 void mailbox_save_set_flags(struct mail_save_context *ctx,
2536 			    enum mail_flags flags,
2537 			    struct mail_keywords *keywords)
2538 {
2539 	struct mailbox *box = ctx->transaction->box;
2540 
2541 	if (ctx->data.keywords != NULL)
2542 		mailbox_keywords_unref(&ctx->data.keywords);
2543 
2544 	ctx->data.flags = flags & ENUM_NEGATE(mailbox_get_private_flags_mask(box));
2545 	ctx->data.pvt_flags = flags & mailbox_get_private_flags_mask(box);
2546 	ctx->data.keywords = keywords;
2547 	if (keywords != NULL)
2548 		mailbox_keywords_ref(keywords);
2549 }
2550 
mailbox_save_copy_flags(struct mail_save_context * ctx,struct mail * mail)2551 void mailbox_save_copy_flags(struct mail_save_context *ctx, struct mail *mail)
2552 {
2553 	const char *const *keywords_list;
2554 	struct mail_keywords *keywords;
2555 
2556 	keywords_list = mail_get_keywords(mail);
2557 	keywords = str_array_length(keywords_list) == 0 ? NULL :
2558 		mailbox_keywords_create_valid(ctx->transaction->box,
2559 					      keywords_list);
2560 	mailbox_save_set_flags(ctx, mail_get_flags(mail), keywords);
2561 	if (keywords != NULL)
2562 		mailbox_keywords_unref(&keywords);
2563 }
2564 
mailbox_save_set_min_modseq(struct mail_save_context * ctx,uint64_t min_modseq)2565 void mailbox_save_set_min_modseq(struct mail_save_context *ctx,
2566 				 uint64_t min_modseq)
2567 {
2568 	ctx->data.min_modseq = min_modseq;
2569 }
2570 
mailbox_save_set_received_date(struct mail_save_context * ctx,time_t received_date,int timezone_offset)2571 void mailbox_save_set_received_date(struct mail_save_context *ctx,
2572 				    time_t received_date, int timezone_offset)
2573 {
2574 	ctx->data.received_date = received_date;
2575 	ctx->data.received_tz_offset = timezone_offset;
2576 }
2577 
mailbox_save_set_save_date(struct mail_save_context * ctx,time_t save_date)2578 void mailbox_save_set_save_date(struct mail_save_context *ctx,
2579 				time_t save_date)
2580 {
2581 	ctx->data.save_date = save_date;
2582 }
2583 
mailbox_save_set_from_envelope(struct mail_save_context * ctx,const char * envelope)2584 void mailbox_save_set_from_envelope(struct mail_save_context *ctx,
2585 				    const char *envelope)
2586 {
2587 	i_free(ctx->data.from_envelope);
2588 	ctx->data.from_envelope = i_strdup(envelope);
2589 }
2590 
mailbox_save_set_uid(struct mail_save_context * ctx,uint32_t uid)2591 void mailbox_save_set_uid(struct mail_save_context *ctx, uint32_t uid)
2592 {
2593 	ctx->data.uid = uid;
2594 }
2595 
mailbox_save_set_guid(struct mail_save_context * ctx,const char * guid)2596 void mailbox_save_set_guid(struct mail_save_context *ctx, const char *guid)
2597 {
2598 	i_assert(guid == NULL || *guid != '\0');
2599 
2600 	i_free(ctx->data.guid);
2601 	ctx->data.guid = i_strdup(guid);
2602 }
2603 
mailbox_save_set_pop3_uidl(struct mail_save_context * ctx,const char * uidl)2604 void mailbox_save_set_pop3_uidl(struct mail_save_context *ctx, const char *uidl)
2605 {
2606 	i_assert(*uidl != '\0');
2607 	i_assert(strchr(uidl, '\n') == NULL);
2608 
2609 	i_free(ctx->data.pop3_uidl);
2610 	ctx->data.pop3_uidl = i_strdup(uidl);
2611 }
2612 
mailbox_save_set_pop3_order(struct mail_save_context * ctx,unsigned int order)2613 void mailbox_save_set_pop3_order(struct mail_save_context *ctx,
2614 				 unsigned int order)
2615 {
2616 	i_assert(order > 0);
2617 
2618 	ctx->data.pop3_order = order;
2619 }
2620 
mailbox_save_get_dest_mail(struct mail_save_context * ctx)2621 struct mail *mailbox_save_get_dest_mail(struct mail_save_context *ctx)
2622 {
2623 	return ctx->dest_mail;
2624 }
2625 
mailbox_save_begin(struct mail_save_context ** ctx,struct istream * input)2626 int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input)
2627 {
2628 	struct mailbox *box = (*ctx)->transaction->box;
2629 	int ret;
2630 
2631 	if (mail_index_is_deleted(box->index)) {
2632 		mailbox_set_deleted(box);
2633 		mailbox_save_cancel(ctx);
2634 		return -1;
2635 	}
2636 
2637 	/* make sure parts get parsed early on */
2638 	const struct mail_storage_settings *mail_set =
2639 		mailbox_get_settings(box);
2640 	if (mail_set->parsed_mail_attachment_detection_add_flags)
2641 		mail_add_temp_wanted_fields((*ctx)->dest_mail,
2642 					    MAIL_FETCH_MESSAGE_PARTS, NULL);
2643 
2644 	if (!(*ctx)->copying_or_moving) {
2645 		/* We're actually saving the mail. We're not being called by
2646 		   mail_storage_copy() because backend didn't support fast
2647 		   copying. */
2648 		i_assert(!(*ctx)->copying_via_save);
2649 		(*ctx)->saving = TRUE;
2650 	} else {
2651 		i_assert((*ctx)->copying_via_save);
2652 	}
2653 	if (box->v.save_begin == NULL) {
2654 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
2655 				       "Saving messages not supported");
2656 		ret = -1;
2657 	} else T_BEGIN {
2658 		ret = box->v.save_begin(*ctx, input);
2659 	} T_END;
2660 
2661 	if (ret < 0) {
2662 		mailbox_save_cancel(ctx);
2663 		return -1;
2664 	}
2665 	return 0;
2666 }
2667 
mailbox_save_continue(struct mail_save_context * ctx)2668 int mailbox_save_continue(struct mail_save_context *ctx)
2669 {
2670 	int ret;
2671 
2672 	T_BEGIN {
2673 		ret = ctx->transaction->box->v.save_continue(ctx);
2674 	} T_END;
2675 	return ret;
2676 }
2677 
2678 static void
mailbox_save_add_pvt_flags(struct mailbox_transaction_context * t,enum mail_flags pvt_flags)2679 mailbox_save_add_pvt_flags(struct mailbox_transaction_context *t,
2680 			   enum mail_flags pvt_flags)
2681 {
2682 	struct mail_save_private_changes *save;
2683 
2684 	if (!array_is_created(&t->pvt_saves))
2685 		i_array_init(&t->pvt_saves, 8);
2686 	save = array_append_space(&t->pvt_saves);
2687 	save->mailnum = t->save_count;
2688 	save->flags = pvt_flags;
2689 }
2690 
2691 static void
mailbox_save_context_reset(struct mail_save_context * ctx,bool success)2692 mailbox_save_context_reset(struct mail_save_context *ctx, bool success)
2693 {
2694 	i_assert(!ctx->unfinished);
2695 	if (!ctx->copying_or_moving) {
2696 		/* we're finishing a save (not copy/move). Note that we could
2697 		   have come here also from mailbox_save_cancel(), in which
2698 		   case ctx->saving may be FALSE. */
2699 		i_assert(!ctx->copying_via_save);
2700 		i_assert(ctx->saving || !success);
2701 		ctx->saving = FALSE;
2702 	} else {
2703 		i_assert(ctx->copying_via_save || !success);
2704 		/* We came from mailbox_copy(). saving==TRUE is possible here
2705 		   if we also came from mailbox_save_using_mail(). Don't set
2706 		   saving=FALSE yet in that case, because copy() is still
2707 		   running. */
2708 	}
2709 }
2710 
mailbox_save_finish(struct mail_save_context ** _ctx)2711 int mailbox_save_finish(struct mail_save_context **_ctx)
2712 {
2713 	struct mail_save_context *ctx = *_ctx;
2714 	struct mailbox_transaction_context *t = ctx->transaction;
2715 	/* we need to keep a copy of this because save_finish implementations
2716 	   will likely zero the data structure during cleanup */
2717 	enum mail_flags pvt_flags = ctx->data.pvt_flags;
2718 	bool copying_via_save = ctx->copying_via_save;
2719 	int ret;
2720 
2721 	/* Do one final continue. The caller may not have done it if the
2722 	   input stream's offset already matched the number of bytes that
2723 	   were wanted to be saved. But due to nested istreams some of the
2724 	   underlying ones may not have seen the EOF yet, and haven't flushed
2725 	   out the pending data. */
2726 	if (mailbox_save_continue(ctx) < 0) {
2727 		mailbox_save_cancel(_ctx);
2728 		return -1;
2729 	}
2730 	*_ctx = NULL;
2731 
2732 	ctx->finishing = TRUE;
2733 	T_BEGIN {
2734 		ret = t->box->v.save_finish(ctx);
2735 	} T_END;
2736 	ctx->finishing = FALSE;
2737 
2738 	if (ret == 0 && !copying_via_save) {
2739 		if (pvt_flags != 0)
2740 			mailbox_save_add_pvt_flags(t, pvt_flags);
2741 		t->save_count++;
2742 	}
2743 
2744 	mailbox_save_context_reset(ctx, TRUE);
2745 	return ret;
2746 }
2747 
mailbox_save_cancel(struct mail_save_context ** _ctx)2748 void mailbox_save_cancel(struct mail_save_context **_ctx)
2749 {
2750 	struct mail_save_context *ctx = *_ctx;
2751 
2752 	*_ctx = NULL;
2753 	T_BEGIN {
2754 		ctx->transaction->box->v.save_cancel(ctx);
2755 	} T_END;
2756 
2757 	/* the dest_mail is no longer valid. if we're still saving
2758 	   more mails, the mail sequence may get reused. make sure
2759 	   the mail gets reset in between */
2760 	mailbox_save_dest_mail_close(ctx);
2761 
2762 	mailbox_save_context_reset(ctx, FALSE);
2763 }
2764 
2765 struct mailbox_transaction_context *
mailbox_save_get_transaction(struct mail_save_context * ctx)2766 mailbox_save_get_transaction(struct mail_save_context *ctx)
2767 {
2768 	return ctx->transaction;
2769 }
2770 
mailbox_copy_int(struct mail_save_context ** _ctx,struct mail * mail)2771 static int mailbox_copy_int(struct mail_save_context **_ctx, struct mail *mail)
2772 {
2773 	struct mail_save_context *ctx = *_ctx;
2774 	struct mailbox_transaction_context *t = ctx->transaction;
2775 	enum mail_flags pvt_flags = ctx->data.pvt_flags;
2776 	struct mail *backend_mail;
2777 	int ret;
2778 
2779 	*_ctx = NULL;
2780 
2781 	if (mail_index_is_deleted(t->box->index)) {
2782 		mailbox_set_deleted(t->box);
2783 		mailbox_save_cancel(&ctx);
2784 		return -1;
2785 	}
2786 
2787 	/* bypass virtual storage, so hard linking can be used whenever
2788 	   possible */
2789 	if (mail_get_backend_mail(mail, &backend_mail) < 0) {
2790 		mailbox_save_cancel(&ctx);
2791 		return -1;
2792 	}
2793 
2794 	i_assert(!ctx->copying_or_moving);
2795 	i_assert(ctx->copy_src_mail == NULL);
2796 	ctx->copying_or_moving = TRUE;
2797 	ctx->copy_src_mail = mail;
2798 	ctx->finishing = TRUE;
2799 	T_BEGIN {
2800 		ret = t->box->v.copy(ctx, backend_mail);
2801 	} T_END;
2802 	ctx->finishing = FALSE;
2803 	if (ret == 0) {
2804 		if (pvt_flags != 0)
2805 			mailbox_save_add_pvt_flags(t, pvt_flags);
2806 		t->save_count++;
2807 	}
2808 	i_assert(!ctx->unfinished);
2809 
2810 	ctx->copy_src_mail = NULL;
2811 	ctx->copying_via_save = FALSE;
2812 	ctx->copying_or_moving = FALSE;
2813 	ctx->saving = FALSE; /* if we came from mailbox_save_using_mail() */
2814 	return ret;
2815 }
2816 
mailbox_copy(struct mail_save_context ** _ctx,struct mail * mail)2817 int mailbox_copy(struct mail_save_context **_ctx, struct mail *mail)
2818 {
2819 	struct mail_save_context *ctx = *_ctx;
2820 
2821 	i_assert(!ctx->saving);
2822 	i_assert(!ctx->moving);
2823 
2824 	int ret;
2825 	T_BEGIN {
2826 		ret = mailbox_copy_int(_ctx, mail);
2827 	} T_END;
2828 
2829 	return ret;
2830 }
2831 
mailbox_move(struct mail_save_context ** _ctx,struct mail * mail)2832 int mailbox_move(struct mail_save_context **_ctx, struct mail *mail)
2833 {
2834 	struct mail_save_context *ctx = *_ctx;
2835 	int ret;
2836 
2837 	i_assert(!ctx->saving);
2838 	i_assert(!ctx->moving);
2839 
2840 	ctx->moving = TRUE;
2841 	T_BEGIN {
2842 		if ((ret = mailbox_copy_int(_ctx, mail)) == 0)
2843 			mail_expunge(mail);
2844 	} T_END;
2845 	ctx->moving = FALSE;
2846 	return ret;
2847 }
2848 
mailbox_save_using_mail(struct mail_save_context ** _ctx,struct mail * mail)2849 int mailbox_save_using_mail(struct mail_save_context **_ctx, struct mail *mail)
2850 {
2851 	struct mail_save_context *ctx = *_ctx;
2852 
2853 	i_assert(!ctx->saving);
2854 	i_assert(!ctx->moving);
2855 
2856 	ctx->saving = TRUE;
2857 	return mailbox_copy_int(_ctx, mail);
2858 }
2859 
mailbox_is_inconsistent(struct mailbox * box)2860 bool mailbox_is_inconsistent(struct mailbox *box)
2861 {
2862 	return box->mailbox_deleted || box->v.is_inconsistent(box);
2863 }
2864 
mailbox_set_deleted(struct mailbox * box)2865 void mailbox_set_deleted(struct mailbox *box)
2866 {
2867 	mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
2868 			       "Mailbox was deleted under us");
2869 	box->mailbox_deleted = TRUE;
2870 }
2871 
get_path_to(struct mailbox * box,enum mailbox_list_path_type type,const char ** internal_path,const char ** path_r)2872 static int get_path_to(struct mailbox *box, enum mailbox_list_path_type type,
2873 		       const char **internal_path, const char **path_r)
2874 {
2875 	int ret;
2876 
2877 	if (internal_path != NULL && *internal_path != NULL) {
2878 		if ((*internal_path)[0] == '\0') {
2879 			*path_r = NULL;
2880 			return 0;
2881 		}
2882 		*path_r = *internal_path;
2883 		return 1;
2884 	}
2885 	ret = mailbox_list_get_path(box->list, box->name, type, path_r);
2886 	if (ret < 0) {
2887 		mail_storage_copy_list_error(box->storage, box->list);
2888 		return -1;
2889 	}
2890 	if (internal_path != NULL && *internal_path == NULL)
2891 		*internal_path = ret == 0 ? "" : p_strdup(box->pool, *path_r);
2892 	return ret;
2893 }
2894 
mailbox_get_path_to(struct mailbox * box,enum mailbox_list_path_type type,const char ** path_r)2895 int mailbox_get_path_to(struct mailbox *box, enum mailbox_list_path_type type,
2896 			const char **path_r)
2897 {
2898 	if (type == MAILBOX_LIST_PATH_TYPE_MAILBOX)
2899 		return get_path_to(box, type, &box->_path, path_r);
2900 	if (type == MAILBOX_LIST_PATH_TYPE_INDEX)
2901 		return get_path_to(box, type, &box->_index_path, path_r);
2902 	return get_path_to(box, type, NULL, path_r);
2903 }
2904 
mailbox_get_path(struct mailbox * box)2905 const char *mailbox_get_path(struct mailbox *box)
2906 {
2907 	i_assert(box->_path != NULL);
2908 	i_assert(box->_path[0] != '\0');
2909 	return box->_path;
2910 }
2911 
mailbox_get_index_path(struct mailbox * box)2912 const char *mailbox_get_index_path(struct mailbox *box)
2913 {
2914 	i_assert(box->_index_path != NULL);
2915 	i_assert(box->_index_path[0] != '\0');
2916 	return box->_index_path;
2917 }
2918 
mailbox_get_permissions_if_not_set(struct mailbox * box)2919 static void mailbox_get_permissions_if_not_set(struct mailbox *box)
2920 {
2921 	if (box->_perm.file_create_mode != 0)
2922 		return;
2923 
2924 	if (box->input != NULL) {
2925 		box->_perm.file_uid = geteuid();
2926 		box->_perm.file_create_mode = 0600;
2927 		box->_perm.dir_create_mode = 0700;
2928 		box->_perm.file_create_gid = (gid_t)-1;
2929 		box->_perm.file_create_gid_origin = "defaults";
2930 		return;
2931 	}
2932 
2933 	struct mailbox_permissions perm;
2934 	mailbox_list_get_permissions(box->list, box->name, &perm);
2935 	mailbox_permissions_copy(&box->_perm, &perm, box->pool);
2936 }
2937 
mailbox_get_permissions(struct mailbox * box)2938 const struct mailbox_permissions *mailbox_get_permissions(struct mailbox *box)
2939 {
2940 	mailbox_get_permissions_if_not_set(box);
2941 
2942 	if (!box->_perm.mail_index_permissions_set && box->index != NULL) {
2943 		box->_perm.mail_index_permissions_set = TRUE;
2944 		mail_index_set_permissions(box->index,
2945 					   box->_perm.file_create_mode,
2946 					   box->_perm.file_create_gid,
2947 					   box->_perm.file_create_gid_origin);
2948 	}
2949 	return &box->_perm;
2950 }
2951 
mailbox_refresh_permissions(struct mailbox * box)2952 void mailbox_refresh_permissions(struct mailbox *box)
2953 {
2954 	i_zero(&box->_perm);
2955 	(void)mailbox_get_permissions(box);
2956 }
2957 
mailbox_create_fd(struct mailbox * box,const char * path,int flags,int * fd_r)2958 int mailbox_create_fd(struct mailbox *box, const char *path, int flags,
2959 		      int *fd_r)
2960 {
2961 	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
2962 	mode_t old_mask;
2963 	int fd;
2964 
2965 	i_assert((flags & O_CREAT) != 0);
2966 
2967 	*fd_r = -1;
2968 
2969 	old_mask = umask(0);
2970 	fd = open(path, flags, perm->file_create_mode);
2971 	umask(old_mask);
2972 
2973 	if (fd != -1) {
2974 		/* ok */
2975 	} else if (errno == EEXIST) {
2976 		/* O_EXCL used, caller will handle this error */
2977 		return 0;
2978 	} else if (errno == ENOENT) {
2979 		mailbox_set_deleted(box);
2980 		return -1;
2981 	} else if (errno == ENOTDIR) {
2982 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
2983 			"Mailbox doesn't allow inferior mailboxes");
2984 		return -1;
2985 	} else if (mail_storage_set_error_from_errno(box->storage)) {
2986 		return -1;
2987 	} else {
2988 		mailbox_set_critical(box, "open(%s, O_CREAT) failed: %m", path);
2989 		return -1;
2990 	}
2991 
2992 	if (perm->file_create_gid != (gid_t)-1) {
2993 		if (fchown(fd, (uid_t)-1, perm->file_create_gid) == 0) {
2994 			/* ok */
2995 		} else if (errno == EPERM) {
2996 			mailbox_set_critical(box, "%s",
2997 				eperm_error_get_chgrp("fchown", path,
2998 					perm->file_create_gid,
2999 					perm->file_create_gid_origin));
3000 		} else {
3001 			mailbox_set_critical(box,
3002 				"fchown(%s) failed: %m", path);
3003 		}
3004 	}
3005 	*fd_r = fd;
3006 	return 1;
3007 }
3008 
mailbox_mkdir(struct mailbox * box,const char * path,enum mailbox_list_path_type type)3009 int mailbox_mkdir(struct mailbox *box, const char *path,
3010 		  enum mailbox_list_path_type type)
3011 {
3012 	const struct mailbox_permissions *perm = mailbox_get_permissions(box);
3013 	const char *root_dir;
3014 
3015 	if (!perm->gid_origin_is_mailbox_path) {
3016 		/* mailbox root directory doesn't exist, create it */
3017 		root_dir = mailbox_list_get_root_forced(box->list, type);
3018 		if (mailbox_list_mkdir_root(box->list, root_dir, type) < 0) {
3019 			mail_storage_copy_list_error(box->storage, box->list);
3020 			return -1;
3021 		}
3022 	}
3023 
3024 	if (mkdir_parents_chgrp(path, perm->dir_create_mode,
3025 				perm->file_create_gid,
3026 				perm->file_create_gid_origin) == 0)
3027 		return 1;
3028 	else if (errno == EEXIST)
3029 		return 0;
3030 	else if (errno == ENOTDIR) {
3031 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
3032 			"Mailbox doesn't allow inferior mailboxes");
3033 		return -1;
3034 	} else if (mail_storage_set_error_from_errno(box->storage)) {
3035 		return -1;
3036 	} else {
3037 		mailbox_set_critical(box, "mkdir_parents(%s) failed: %m", path);
3038 		return -1;
3039 	}
3040 }
3041 
mailbox_create_missing_dir(struct mailbox * box,enum mailbox_list_path_type type)3042 int mailbox_create_missing_dir(struct mailbox *box,
3043 			       enum mailbox_list_path_type type)
3044 {
3045 	const char *mail_dir, *dir;
3046 	struct stat st;
3047 	int ret;
3048 
3049 	if ((ret = mailbox_get_path_to(box, type, &dir)) <= 0)
3050 		return ret;
3051 	if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
3052 				&mail_dir) < 0)
3053 		return -1;
3054 	if (null_strcmp(dir, mail_dir) != 0) {
3055 		/* Mailbox directory is different - create a missing dir */
3056 	} else if ((box->list->props & MAILBOX_LIST_PROP_AUTOCREATE_DIRS) != 0) {
3057 		/* This layout (e.g. imapc) wants to autocreate missing mailbox
3058 		   directories as well. */
3059 	} else {
3060 		/* If the mailbox directory doesn't exist, the mailbox
3061 		   shouldn't exist at all. So just assume that it's already
3062 		   created and if there's a race condition just fail later. */
3063 		return 0;
3064 	}
3065 
3066 	/* we call this function even when the directory exists, so first do a
3067 	   quick check to see if we need to mkdir anything */
3068 	if (stat(dir, &st) == 0)
3069 		return 0;
3070 
3071 	if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) == 0 &&
3072 	    null_strcmp(dir, mail_dir) != 0 && mail_dir != NULL &&
3073 	    stat(mail_dir, &st) < 0 && (errno == ENOENT || errno == ENOTDIR)) {
3074 		/* Race condition - mail root directory doesn't exist
3075 		   anymore either. We shouldn't create this directory
3076 		   anymore. */
3077 		mailbox_set_deleted(box);
3078 		return -1;
3079 	}
3080 
3081 	return mailbox_mkdir(box, dir, type);
3082 }
3083 
mail_storage_get_lock_timeout(struct mail_storage * storage,unsigned int secs)3084 unsigned int mail_storage_get_lock_timeout(struct mail_storage *storage,
3085 					   unsigned int secs)
3086 {
3087 	return storage->set->mail_max_lock_timeout == 0 ? secs :
3088 		I_MIN(secs, storage->set->mail_max_lock_timeout);
3089 }
3090 
3091 enum mail_index_open_flags
mail_storage_settings_to_index_flags(const struct mail_storage_settings * set)3092 mail_storage_settings_to_index_flags(const struct mail_storage_settings *set)
3093 {
3094 	enum mail_index_open_flags index_flags = 0;
3095 
3096 #ifndef MMAP_CONFLICTS_WRITE
3097 	if (set->mmap_disable)
3098 #endif
3099 		index_flags |= MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE;
3100 	if (set->dotlock_use_excl)
3101 		index_flags |= MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL;
3102 	if (set->mail_nfs_index)
3103 		index_flags |= MAIL_INDEX_OPEN_FLAG_NFS_FLUSH;
3104 	return index_flags;
3105 }
3106 
mail_parse_human_timestamp(const char * str,time_t * timestamp_r,bool * utc_r)3107 int mail_parse_human_timestamp(const char *str, time_t *timestamp_r,
3108 			       bool *utc_r)
3109 {
3110 	struct tm tm;
3111 	unsigned int secs;
3112 	const char *error;
3113 
3114 	if (i_isdigit(str[0]) && i_isdigit(str[1]) &&
3115 	    i_isdigit(str[2]) && i_isdigit(str[3]) && str[4] == '-' &&
3116 	    i_isdigit(str[5]) && i_isdigit(str[6]) && str[7] == '-' &&
3117 	    i_isdigit(str[8]) && i_isdigit(str[9]) && str[10] == '\0') {
3118 		/* yyyy-mm-dd */
3119 		i_zero(&tm);
3120 		tm.tm_year = (str[0]-'0') * 1000 + (str[1]-'0') * 100 +
3121 			(str[2]-'0') * 10 + (str[3]-'0') - 1900;
3122 		tm.tm_mon = (str[5]-'0') * 10 + (str[6]-'0') - 1;
3123 		tm.tm_mday = (str[8]-'0') * 10 + (str[9]-'0');
3124 		*timestamp_r = mktime(&tm);
3125 		*utc_r = FALSE;
3126 		return 0;
3127 	} else if (imap_parse_date(str, timestamp_r)) {
3128 		/* imap date */
3129 		*utc_r = FALSE;
3130 		return 0;
3131 	} else if (str_to_time(str, timestamp_r) == 0) {
3132 		/* unix timestamp */
3133 		*utc_r = TRUE;
3134 		return 0;
3135 	} else if (settings_get_time(str, &secs, &error) == 0) {
3136 		*timestamp_r = ioloop_time - secs;
3137 		*utc_r = TRUE;
3138 		return 0;
3139 	} else {
3140 		return -1;
3141 	}
3142 }
3143 
mail_set_mail_cache_corrupted(struct mail * mail,const char * fmt,...)3144 void mail_set_mail_cache_corrupted(struct mail *mail, const char *fmt, ...)
3145 {
3146 	struct mail_cache_view *cache_view =
3147 		mail->transaction->cache_view;
3148 
3149 	i_assert(cache_view != NULL);
3150 
3151 	va_list va;
3152 	va_start(va, fmt);
3153 
3154 	T_BEGIN {
3155 		mail_cache_set_seq_corrupted_reason(cache_view, mail->seq,
3156 			t_strdup_printf("UID %u: %s",
3157 					mail->uid,
3158 					t_strdup_vprintf(fmt, va)));
3159 	} T_END;
3160 
3161 	/* update also the storage's internal error */
3162 	mailbox_set_index_error(mail->box);
3163 
3164 	va_end(va);
3165 }
3166 
3167 static int
mail_storage_dotlock_create(const char * lock_path,const struct file_create_settings * lock_set,const struct mail_storage_settings * mail_set,struct file_lock ** lock_r,const char ** error_r)3168 mail_storage_dotlock_create(const char *lock_path,
3169 			    const struct file_create_settings *lock_set,
3170 			    const struct mail_storage_settings *mail_set,
3171 			    struct file_lock **lock_r, const char **error_r)
3172 {
3173 	const struct dotlock_settings dotlock_set = {
3174 		.timeout = lock_set->lock_timeout_secs,
3175 		.stale_timeout = I_MAX(60*5, lock_set->lock_timeout_secs),
3176 		.lock_suffix = "",
3177 
3178 		.use_excl_lock = mail_set->dotlock_use_excl,
3179 		.nfs_flush = mail_set->mail_nfs_storage,
3180 		.use_io_notify = TRUE,
3181 	};
3182 	struct dotlock *dotlock;
3183 	int ret = file_dotlock_create(&dotlock_set, lock_path, 0, &dotlock);
3184 	if (ret <= 0) {
3185 		*error_r = t_strdup_printf("file_dotlock_create(%s) failed: %m",
3186 					   lock_path);
3187 		return ret;
3188 	}
3189 	*lock_r = file_lock_from_dotlock(&dotlock);
3190 	return 1;
3191 }
3192 
mail_storage_lock_create(const char * lock_path,const struct file_create_settings * lock_set,const struct mail_storage_settings * mail_set,struct file_lock ** lock_r,const char ** error_r)3193 int mail_storage_lock_create(const char *lock_path,
3194 			     const struct file_create_settings *lock_set,
3195 			     const struct mail_storage_settings *mail_set,
3196 			     struct file_lock **lock_r, const char **error_r)
3197 {
3198 	struct file_create_settings lock_set_new = *lock_set;
3199 	bool created;
3200 
3201 	if (lock_set->lock_settings.lock_method == FILE_LOCK_METHOD_DOTLOCK)
3202 		return mail_storage_dotlock_create(lock_path, lock_set, mail_set, lock_r, error_r);
3203 
3204 	lock_set_new.lock_settings.close_on_free = TRUE;
3205 	lock_set_new.lock_settings.unlink_on_free = TRUE;
3206 	if (file_create_locked(lock_path, &lock_set_new, lock_r,
3207 			       &created, error_r) == -1) {
3208 		*error_r = t_strdup_printf("file_create_locked(%s) failed: %s",
3209 					   lock_path, *error_r);
3210 		return errno == EAGAIN ? 0 : -1;
3211 	}
3212 	return 1;
3213 }
3214 
mailbox_lock_file_create(struct mailbox * box,const char * lock_fname,unsigned int lock_secs,struct file_lock ** lock_r,const char ** error_r)3215 int mailbox_lock_file_create(struct mailbox *box, const char *lock_fname,
3216 			     unsigned int lock_secs, struct file_lock **lock_r,
3217 			     const char **error_r)
3218 {
3219 	const struct mailbox_permissions *perm;
3220 	struct file_create_settings set;
3221 	const char *lock_path;
3222 
3223 	perm = mailbox_get_permissions(box);
3224 	i_zero(&set);
3225 	set.lock_timeout_secs =
3226 		mail_storage_get_lock_timeout(box->storage, lock_secs);
3227 	set.lock_settings.lock_method = box->storage->set->parsed_lock_method;
3228 	set.mode = perm->file_create_mode;
3229 	set.gid = perm->file_create_gid;
3230 	set.gid_origin = perm->file_create_gid_origin;
3231 
3232 	if (box->list->set.volatile_dir == NULL)
3233 		lock_path = t_strdup_printf("%s/%s", box->index->dir, lock_fname);
3234 	else {
3235 		unsigned char box_name_sha1[SHA1_RESULTLEN];
3236 		string_t *str = t_str_new(128);
3237 
3238 		/* Keep this simple: Use the lock_fname with a SHA1 of the
3239 		   mailbox name as the suffix. The mailbox name itself could
3240 		   be too large as a filename and creating the full directory
3241 		   structure would be pretty troublesome. It would also make
3242 		   it more difficult to perform the automated deletion of empty
3243 		   lock directories. */
3244 		str_printfa(str, "%s/%s.", box->list->set.volatile_dir,
3245 			    lock_fname);
3246 		sha1_get_digest(box->name, strlen(box->name), box_name_sha1);
3247 		binary_to_hex_append(str, box_name_sha1, sizeof(box_name_sha1));
3248 		lock_path = str_c(str);
3249 		set.mkdir_mode = 0700;
3250 	}
3251 
3252 	return mail_storage_lock_create(lock_path, &set,
3253 					box->storage->set, lock_r, error_r);
3254 }
3255 
mailbox_sync_notify(struct mailbox * box,uint32_t uid,enum mailbox_sync_type sync_type)3256 void mailbox_sync_notify(struct mailbox *box, uint32_t uid,
3257 			 enum mailbox_sync_type sync_type)
3258 {
3259 	if (box->v.sync_notify != NULL)
3260 		box->v.sync_notify(box, uid, sync_type);
3261 
3262 	/* Send an event for expunged mail. */
3263 	if (sync_type == MAILBOX_SYNC_TYPE_EXPUNGE) {
3264 		e_debug(event_create_passthrough(box->event)->
3265 			set_name("mail_expunged")->
3266 			add_int("uid", uid)->event(),
3267 			"UID %u: Mail expunged", uid);
3268 	}
3269 }
3270