1 /* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
2  */
3 
4 #include "lib.h"
5 #include "array.h"
6 #include "str-sanitize.h"
7 #include "home-expand.h"
8 #include "eacces-error.h"
9 #include "mkdir-parents.h"
10 #include "ioloop.h"
11 
12 #include "sieve-common.h"
13 #include "sieve-settings.h"
14 #include "sieve-error-private.h"
15 
16 #include "sieve-script-private.h"
17 #include "sieve-storage-private.h"
18 
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <time.h>
23 #include <utime.h>
24 
25 #define CRITICAL_MSG \
26   "Internal error occurred. Refer to server log for more information."
27 #define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
28 
29 struct event_category event_category_sieve_storage = {
30 	.parent = &event_category_sieve,
31 	.name = "sieve-storage",
32 };
33 
34 /*
35  * Storage class
36  */
37 
38 struct sieve_storage_class_registry {
39 	ARRAY_TYPE(sieve_storage_class) storage_classes;
40 };
41 
sieve_storages_init(struct sieve_instance * svinst)42 void sieve_storages_init(struct sieve_instance *svinst)
43 {
44 	svinst->storage_reg = p_new(svinst->pool,
45 				    struct sieve_storage_class_registry, 1);
46 	p_array_init(&svinst->storage_reg->storage_classes, svinst->pool, 8);
47 
48 	sieve_storage_class_register(svinst, &sieve_file_storage);
49 	sieve_storage_class_register(svinst, &sieve_dict_storage);
50 	sieve_storage_class_register(svinst, &sieve_ldap_storage);
51 }
52 
sieve_storages_deinit(struct sieve_instance * svinst ATTR_UNUSED)53 void sieve_storages_deinit(struct sieve_instance *svinst ATTR_UNUSED)
54 {
55 	/* nothing yet */
56 }
57 
sieve_storage_class_register(struct sieve_instance * svinst,const struct sieve_storage * storage_class)58 void sieve_storage_class_register(struct sieve_instance *svinst,
59 				  const struct sieve_storage *storage_class)
60 {
61 	struct sieve_storage_class_registry *reg = svinst->storage_reg;
62 	const struct sieve_storage *old_class;
63 
64 	old_class = sieve_storage_find_class(svinst,
65 					     storage_class->driver_name);
66 	if (old_class != NULL) {
67 		if (old_class->v.alloc == NULL) {
68 			/* replacing a "support not compiled in" storage class
69 			 */
70 			sieve_storage_class_unregister(svinst, old_class);
71 		} else {
72 			i_panic("sieve_storage_class_register(%s): "
73 				"Already registered",
74 				storage_class->driver_name);
75 		}
76 	}
77 
78 	array_append(&reg->storage_classes, &storage_class, 1);
79 }
80 
sieve_storage_class_unregister(struct sieve_instance * svinst,const struct sieve_storage * storage_class)81 void sieve_storage_class_unregister(struct sieve_instance *svinst,
82 				    const struct sieve_storage *storage_class)
83 {
84 	struct sieve_storage_class_registry *reg = svinst->storage_reg;
85 	const struct sieve_storage *const *classes;
86 	unsigned int i, count;
87 
88 	classes = array_get(&reg->storage_classes, &count);
89 	for (i = 0; i < count; i++) {
90 		if (classes[i] == storage_class) {
91 			array_delete(&reg->storage_classes, i, 1);
92 			break;
93 		}
94 	}
95 }
96 
97 const struct sieve_storage *
sieve_storage_find_class(struct sieve_instance * svinst,const char * name)98 sieve_storage_find_class(struct sieve_instance *svinst, const char *name)
99 {
100 	struct sieve_storage_class_registry *reg = svinst->storage_reg;
101 	const struct sieve_storage *const *classes;
102 	unsigned int i, count;
103 
104 	i_assert(name != NULL);
105 
106 	classes = array_get(&reg->storage_classes, &count);
107 	for (i = 0; i < count; i++) {
108 		if (strcasecmp(classes[i]->driver_name, name) == 0)
109 			return classes[i];
110 	}
111 	return NULL;
112 }
113 
114 /*
115  * Storage instance
116  */
117 
split_next_arg(const char * const ** _args)118 static const char *split_next_arg(const char *const **_args)
119 {
120 	const char *const *args = *_args;
121 	const char *str = args[0];
122 
123 	/* join arguments for escaped ";" separator */
124 
125 	args++;
126 	while (*args != NULL && **args == '\0') {
127 		args++;
128 		if (*args == NULL) {
129 			/* string ends with ";", just ignore it. */
130 			break;
131 		}
132 		str = t_strconcat(str, ";", *args, NULL);
133 		args++;
134 	}
135 	*_args = args;
136 	return str;
137 }
138 
139 static int
sieve_storage_driver_parse(struct sieve_instance * svinst,const char ** data,const struct sieve_storage ** driver_r)140 sieve_storage_driver_parse(struct sieve_instance *svinst, const char **data,
141 			   const struct sieve_storage **driver_r)
142 {
143 	const struct sieve_storage *storage_class = NULL;
144 	const char *p;
145 
146 	p = strchr(*data, ':');
147 	if (p == NULL)
148 		return 0;
149 
150 	/* Lookup storage driver */
151 	T_BEGIN {
152 		const char *driver;
153 
154 		driver = t_strdup_until(*data, p);
155 		*data = p+1;
156 
157 		storage_class = sieve_storage_find_class(svinst, driver);
158 		if (storage_class == NULL) {
159 			e_error(svinst->event,
160 				"Unknown storage driver module `%s'",
161 				driver);
162 		} else if (storage_class->v.alloc == NULL) {
163 			e_error(svinst->event,
164 				"Support not compiled in for storage driver `%s'",
165 				driver);
166 			storage_class = NULL;
167 		}
168 	} T_END;
169 
170 	*driver_r = storage_class;
171 	return (storage_class == NULL ? -1 : 1);
172 }
173 
174 static int
sieve_storage_data_parse(struct sieve_storage * storage,const char * data,const char ** location_r,const char * const ** options_r)175 sieve_storage_data_parse(struct sieve_storage *storage, const char *data,
176 			 const char **location_r, const char *const **options_r)
177 {
178 	ARRAY_TYPE(const_string) options;
179 	const char *const *tmp;
180 
181 	if (*data == '\0') {
182 		*options_r = NULL;
183 		*location_r = data;
184 		return 0;
185 	}
186 
187 	/* <location> */
188 	tmp = t_strsplit(data, ";");
189 	*location_r = split_next_arg(&tmp);
190 
191 	if (options_r != NULL) {
192 		t_array_init(&options, 8);
193 
194 		/* [<option> *(';' <option>)] */
195 		while (*tmp != NULL) {
196 			const char *option = split_next_arg(&tmp);
197 
198 			if (strncasecmp(option, "name=", 5) == 0) {
199 				if (option[5] == '\0') {
200 					e_error(storage->event,
201 						"Failed to parse storage location: "
202 						"Empty name not allowed");
203 					return -1;
204 				}
205 
206 				if (storage->script_name == NULL) {
207 					if (!sieve_script_name_is_valid(option+5)) {
208 						e_error(storage->event,
209 							"Failed to parse storage location: "
210 							"Invalid script name `%s'.",
211 							str_sanitize(option+5, 80));
212 						return -1;
213 					}
214 					storage->script_name = p_strdup(storage->pool, option+5);
215 				}
216 
217 			} else if (strncasecmp(option, "bindir=", 7) == 0) {
218 				const char *bin_dir = option+7;
219 
220 				if (bin_dir[0] == '\0') {
221 					e_error(storage->event,
222 						"Failed to parse storage location: "
223 						"Empty bindir not allowed");
224 					return -1;
225 				}
226 
227 				if (bin_dir[0] == '~') {
228 					/* home-relative path. change to absolute. */
229 					const char *home = sieve_environment_get_homedir(storage->svinst);
230 
231 					if (home != NULL) {
232 						bin_dir = home_expand_tilde(bin_dir, home);
233 					} else if (bin_dir[1] == '/' || bin_dir[1] == '\0') {
234 						e_error(storage->event,
235 							"Failed to parse storage location: "
236 							"bindir is relative to home directory (~/), "
237 							"but home directory cannot be determined");
238 						return -1;
239 					}
240 				}
241 
242 				storage->bin_dir = p_strdup(storage->pool, bin_dir);
243 			} else {
244 				array_append(&options, &option, 1);
245 			}
246 		}
247 
248 		(void)array_append_space(&options);
249 		*options_r = array_idx(&options, 0);
250 	}
251 
252 	return 0;
253 }
254 
255 struct event *
sieve_storage_event_create(struct sieve_instance * svinst,const struct sieve_storage * storage_class)256 sieve_storage_event_create(struct sieve_instance *svinst,
257 			   const struct sieve_storage *storage_class)
258 {
259 	struct event *event;
260 
261 	event = event_create(svinst->event);
262 	event_add_category(event, &event_category_sieve_storage);
263 	event_add_str(event, "driver", storage_class->driver_name);
264 	event_set_append_log_prefix(
265 		event, t_strdup_printf("%s storage: ",
266 				       storage_class->driver_name));
267 
268 	return event;
269 }
270 
271 struct sieve_storage *
sieve_storage_alloc(struct sieve_instance * svinst,struct event * event,const struct sieve_storage * storage_class,const char * data,enum sieve_storage_flags flags,bool main)272 sieve_storage_alloc(struct sieve_instance *svinst, struct event *event,
273 		    const struct sieve_storage *storage_class, const char *data,
274 		    enum sieve_storage_flags flags, bool main)
275 {
276 	struct sieve_storage *storage;
277 
278 	i_assert(storage_class->v.alloc != NULL);
279 	storage = storage_class->v.alloc();
280 
281 	storage->storage_class = storage_class;
282 	storage->refcount = 1;
283 	storage->svinst = svinst;
284 	storage->flags = flags;
285 	storage->data = p_strdup_empty(storage->pool, data);
286 	storage->main_storage = main;
287 
288 	if (event != NULL) {
289 		storage->event = event;
290 		event_ref(storage->event);
291 	} else {
292 		storage->event =
293 			sieve_storage_event_create(svinst, storage_class);
294 	}
295 
296 	return storage;
297 }
298 
299 static struct sieve_storage *
sieve_storage_init(struct sieve_instance * svinst,const struct sieve_storage * storage_class,const char * data,enum sieve_storage_flags flags,bool main,enum sieve_error * error_r)300 sieve_storage_init(struct sieve_instance *svinst,
301 		   const struct sieve_storage *storage_class, const char *data,
302 		   enum sieve_storage_flags flags, bool main,
303 		   enum sieve_error *error_r)
304 {
305 	struct sieve_storage *storage;
306 	const char *const *options;
307 	const char *location;
308 	struct event *event;
309 	enum sieve_error error;
310 
311 	if (error_r != NULL)
312 		*error_r = SIEVE_ERROR_NONE;
313 	else
314 		error_r = &error;
315 
316 	i_assert(storage_class->v.init != NULL);
317 
318 	event = sieve_storage_event_create(svinst, storage_class);
319 
320 	if ((flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 &&
321 	    !storage_class->allows_synchronization) {
322 		e_debug(event, "Storage does not support synchronization");
323 		*error_r = SIEVE_ERROR_NOT_POSSIBLE;
324 		event_unref(&event);
325 		return NULL;
326 	}
327 
328 	if ((flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 &&
329 	    storage_class->v.save_init == NULL) {
330 		e_error(event, "Storage does not support write access");
331 		*error_r = SIEVE_ERROR_TEMP_FAILURE;
332 		event_unref(&event);
333 		return NULL;
334 	}
335 
336 	T_BEGIN {
337 		storage = sieve_storage_alloc(svinst, event, storage_class,
338 					      data, flags, main);
339 
340 		if (sieve_storage_data_parse(storage, data,
341 					     &location, &options) < 0) {
342 			*error_r = SIEVE_ERROR_TEMP_FAILURE;
343 			sieve_storage_unref(&storage);
344 			storage = NULL;
345 		} else {
346 			storage->location = p_strdup(storage->pool, location);
347 
348 			event_add_str(event, "script_location",
349 				      storage->location);
350 
351 			if (storage_class->v.init(storage, options,
352 						  error_r) < 0) {
353 				sieve_storage_unref(&storage);
354 				storage = NULL;
355 			}
356 		}
357 	} T_END;
358 
359 	event_unref(&event);
360 	return storage;
361 }
362 
363 struct sieve_storage *
sieve_storage_create(struct sieve_instance * svinst,const char * location,enum sieve_storage_flags flags,enum sieve_error * error_r)364 sieve_storage_create(struct sieve_instance *svinst, const char *location,
365 		     enum sieve_storage_flags flags, enum sieve_error *error_r)
366 {
367 	const struct sieve_storage *storage_class;
368 	enum sieve_error error;
369 	const char *data;
370 	int ret;
371 
372 	/* Dont use this function for creating a synchronizing storage */
373 	i_assert((flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0);
374 
375 	if (error_r != NULL)
376 		*error_r = SIEVE_ERROR_NONE;
377 	else
378 		error_r = &error;
379 
380 	data = location;
381 	if ((ret = sieve_storage_driver_parse(svinst, &data,
382 					      &storage_class)) < 0) {
383 		*error_r = SIEVE_ERROR_TEMP_FAILURE;
384 		return NULL;
385 	}
386 
387 	if (ret == 0)
388 		storage_class = &sieve_file_storage;
389 
390 	return sieve_storage_init(svinst, storage_class, data, flags,
391 				  FALSE, error_r);
392 }
393 
394 static struct sieve_storage *
sieve_storage_do_create_main(struct sieve_instance * svinst,struct mail_user * user,enum sieve_storage_flags flags,enum sieve_error * error_r)395 sieve_storage_do_create_main(struct sieve_instance *svinst,
396 			     struct mail_user *user,
397 			     enum sieve_storage_flags flags,
398 			     enum sieve_error *error_r)
399 {
400 	struct sieve_storage *storage = NULL;
401 	const struct sieve_storage
402 		*sieve_class = NULL,
403 		*sieve_dir_class = NULL;
404 	const char *set_sieve, *set_sieve_dir;
405 	const char *data, *storage_path;
406 	unsigned long long int uint_setting;
407 	size_t size_setting;
408 	int ret;
409 
410 	/* Sieve storage location */
411 
412 	set_sieve = sieve_setting_get(svinst, "sieve");
413 
414 	if (set_sieve != NULL) {
415 		if (*set_sieve == '\0') {
416 			/* disabled */
417 			e_debug(svinst->event, "storage: "
418 				"Personal storage is disabled (sieve=\"\")");
419 			*error_r = SIEVE_ERROR_NOT_FOUND;
420 			return NULL;
421 		}
422 
423 		data = set_sieve;
424 		if ((ret = sieve_storage_driver_parse(svinst, &data,
425 						      &sieve_class)) < 0) {
426 			*error_r = SIEVE_ERROR_TEMP_FAILURE;
427 			return NULL;
428 		}
429 
430 		if (ret > 0) {
431 			/* The normal case: explicit driver name */
432 			storage = sieve_storage_init(svinst, sieve_class, data,
433 						     flags, TRUE, error_r);
434 			if (storage == NULL)
435 				return NULL;
436 		}
437 
438 		/* No driver name */
439 	}
440 
441 	if (storage == NULL) {
442 		/* Script storage directory configuration (deprecated) */
443 
444 		set_sieve_dir = sieve_setting_get(svinst, "sieve_dir");
445 		if (set_sieve_dir == NULL) {
446 			set_sieve_dir = sieve_setting_get(svinst,
447 							  "sieve_storage");
448 		}
449 
450 		if (set_sieve_dir == NULL || *set_sieve_dir == '\0') {
451 			storage_path = "";
452 		} else {
453 			const char *p;
454 
455 			/* Parse and check driver */
456 			storage_path = set_sieve_dir;
457 			if ((ret = sieve_storage_driver_parse(
458 				svinst, &storage_path, &sieve_dir_class)) < 0) {
459 				*error_r = SIEVE_ERROR_TEMP_FAILURE;
460 				return NULL;
461 			}
462 
463 			if (ret > 0 && sieve_dir_class != &sieve_file_storage) {
464 				e_error(svinst->event, "storage: "
465 					"Cannot use deprecated sieve_dir= setting "
466 					"with `%s' driver for main Sieve storage",
467 					sieve_dir_class->driver_name);
468 			}
469 
470 			/* Ignore any options */
471 			p = strchr(storage_path, ';');
472 			if (p != NULL)
473 				storage_path = t_strdup_until(storage_path, p);
474 		}
475 
476 		storage = sieve_file_storage_init_legacy(svinst, set_sieve,
477 							 storage_path, flags,
478 							 error_r);
479 	}
480 
481 	if (storage == NULL)
482 		return NULL;
483 
484 	(void)sieve_storage_sync_init(storage, user);
485 
486 	/* Get quota settings if storage driver provides none */
487 
488 	if (storage->max_storage == 0 &&
489 	    sieve_setting_get_size_value(svinst, "sieve_quota_max_storage",
490 					 &size_setting)) {
491 		storage->max_storage = size_setting;
492 	}
493 
494 	if (storage->max_scripts == 0 &&
495 	    sieve_setting_get_uint_value(svinst, "sieve_quota_max_scripts",
496 					 &uint_setting)) {
497 		storage->max_scripts = uint_setting;
498 	}
499 
500 	if (storage->max_storage > 0) {
501 		e_debug(storage->event, "quota: "
502 			"Storage limit: %llu bytes",
503 			(unsigned long long int) storage->max_storage);
504 	}
505 	if (storage->max_scripts > 0) {
506 		e_debug(storage->event, "quota: "
507 			"Script count limit: %llu scripts",
508 			(unsigned long long int) storage->max_scripts);
509 	}
510 	return storage;
511 }
512 
513 struct sieve_storage *
sieve_storage_create_main(struct sieve_instance * svinst,struct mail_user * user,enum sieve_storage_flags flags,enum sieve_error * error_r)514 sieve_storage_create_main(struct sieve_instance *svinst, struct mail_user *user,
515 			  enum sieve_storage_flags flags,
516 			  enum sieve_error *error_r)
517 {
518 	struct sieve_storage *storage;
519 	const char *set_enabled, *set_default, *set_default_name;
520 	enum sieve_error error;
521 
522 	if (error_r != NULL)
523 		*error_r = SIEVE_ERROR_NONE;
524 	else
525 		error_r = &error;
526 
527 	/* Check whether Sieve is disabled for this user */
528 	if ((set_enabled = sieve_setting_get(svinst, "sieve_enabled")) != NULL &&
529 	    strcasecmp(set_enabled, "no") == 0) {
530 		e_debug(svinst->event,
531 			"Sieve is disabled for this user");
532 		*error_r = SIEVE_ERROR_NOT_POSSIBLE;
533 		return NULL;
534 	}
535 
536 	/* Determine location for default script */
537 	set_default = sieve_setting_get(svinst, "sieve_default");
538 	if (set_default == NULL) {
539 		/* For backwards compatibility */
540 		set_default = sieve_setting_get(svinst, "sieve_global_path");
541 	}
542 
543 	/* Attempt to locate user's main storage */
544 	storage = sieve_storage_do_create_main(svinst, user, flags, error_r);
545 	if (storage != NULL) {
546 		/* Success; record default script location for later use */
547 		storage->default_location =
548 			p_strdup_empty(storage->pool, set_default);
549 
550 		set_default_name =
551 			sieve_setting_get(svinst, "sieve_default_name");
552 		if (set_default_name != NULL && *set_default_name != '\0' &&
553 		    !sieve_script_name_is_valid(set_default_name)) {
554 			e_error(storage->event,
555 				"Invalid script name `%s' for `sieve_default_name' setting.",
556 				str_sanitize(set_default_name, 80));
557 			set_default_name = NULL;
558 		}
559 		storage->default_name =
560 			p_strdup_empty(storage->pool, set_default_name);
561 
562 		if (storage->default_location != NULL &&
563 			storage->default_name != NULL) {
564 			e_debug(storage->event,
565 				"Default script at `%s' is visible by name `%s'",
566 				storage->default_location, storage->default_name);
567 		}
568 	} else if (*error_r != SIEVE_ERROR_TEMP_FAILURE &&
569 		   (flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 &&
570 		   (flags & SIEVE_STORAGE_FLAG_READWRITE) == 0) {
571 
572 		/* Failed; try using default script location
573 		   (not for temporary failures, read/write access, or dsync) */
574 		if (set_default == NULL) {
575 			e_debug(svinst->event, "storage: "
576 				"No default script location configured");
577 		} else {
578 			e_debug(svinst->event, "storage: "
579 				"Trying default script location `%s'",
580 				set_default);
581 
582 			storage = sieve_storage_create(svinst, set_default, 0,
583 						       error_r);
584 			if (storage == NULL) {
585 				switch (*error_r) {
586 				case SIEVE_ERROR_NOT_FOUND:
587 					e_debug(svinst->event, "storage: "
588 						"Default script location `%s' not found",
589 						set_default);
590 					break;
591 				case SIEVE_ERROR_TEMP_FAILURE:
592 					e_error(svinst->event, "storage: "
593 						"Failed to access default script location `%s' "
594 						"(temporary failure)",
595 						set_default);
596 					break;
597 				default:
598 					e_error(svinst->event, "storage: "
599 						"Failed to access default script location `%s'",
600 						set_default);
601 					break;
602 				}
603 			}
604 		}
605 		if (storage != NULL)
606 			storage->is_default = TRUE;
607 	}
608 	return storage;
609 }
610 
sieve_storage_ref(struct sieve_storage * storage)611 void sieve_storage_ref(struct sieve_storage *storage)
612 {
613 	storage->refcount++;
614 }
615 
sieve_storage_unref(struct sieve_storage ** _storage)616 void sieve_storage_unref(struct sieve_storage **_storage)
617 {
618 	struct sieve_storage *storage = *_storage;
619 
620 	i_assert(storage->refcount > 0);
621 
622 	if (--storage->refcount != 0)
623 		return;
624 
625 	if (storage->default_for != NULL) {
626 		i_assert(storage->is_default);
627 		sieve_storage_unref(&storage->default_for);
628 	}
629 
630 	sieve_storage_sync_deinit(storage);
631 
632 	if (storage->v.destroy != NULL)
633 		storage->v.destroy(storage);
634 
635 	i_free(storage->error);
636 	event_unref(&storage->event);
637 	pool_unref(&storage->pool);
638 	*_storage = NULL;
639 }
640 
sieve_storage_setup_bindir(struct sieve_storage * storage,mode_t mode)641 int sieve_storage_setup_bindir(struct sieve_storage *storage, mode_t mode)
642 {
643 	const char *bin_dir = storage->bin_dir;
644 	struct stat st;
645 
646 	if (bin_dir == NULL)
647 		return -1;
648 
649 	if (stat(bin_dir, &st) == 0)
650 		return 0;
651 
652 	if (errno == EACCES) {
653 		e_error(storage->event,
654 			"Failed to setup directory for binaries: "
655 			"%s",	eacces_error_get("stat", bin_dir));
656 		return -1;
657 	} else if (errno != ENOENT) {
658 		e_error(storage->event,
659 			"Failed to setup directory for binaries: "
660 			"stat(%s) failed: %m",
661 			bin_dir);
662 		return -1;
663 	}
664 
665 	if (mkdir_parents(bin_dir, mode) == 0) {
666 		e_debug(storage->event,
667 			"Created directory for binaries: %s", bin_dir);
668 		return 1;
669 	}
670 
671 	switch (errno) {
672 	case EEXIST:
673 		return 0;
674 	case ENOENT:
675 		e_error(storage->event,
676 			"Directory for binaries was deleted while it was being created");
677 		break;
678 	case EACCES:
679 		e_error(storage->event,
680 			"%s",	eacces_error_get_creating("mkdir_parents_chgrp", bin_dir));
681 		break;
682 	default:
683 		e_error(storage->event,
684 			"mkdir_parents_chgrp(%s) failed: %m", bin_dir);
685 		break;
686 	}
687 
688 	return -1;
689 }
690 
sieve_storage_is_singular(struct sieve_storage * storage)691 int sieve_storage_is_singular(struct sieve_storage *storage)
692 {
693 	if (storage->v.is_singular == NULL)
694 		return 1;
695 	return storage->v.is_singular(storage);
696 }
697 
sieve_storage_get_last_change(struct sieve_storage * storage,time_t * last_change_r)698 int sieve_storage_get_last_change(struct sieve_storage *storage,
699 				  time_t *last_change_r)
700 {
701 	i_assert(storage->v.get_last_change != NULL);
702 	return storage->v.get_last_change(storage, last_change_r);
703 }
704 
sieve_storage_set_modified(struct sieve_storage * storage,time_t mtime)705 void sieve_storage_set_modified(struct sieve_storage *storage, time_t mtime)
706 {
707 	if (storage->v.set_modified == NULL)
708 		return;
709 
710 	storage->v.set_modified(storage, mtime);
711 }
712 
713 /*
714  * Script access
715  */
716 
717 static struct sieve_script *
sieve_storage_get_script_direct(struct sieve_storage * storage,const char * name,enum sieve_error * error_r)718 sieve_storage_get_script_direct(struct sieve_storage *storage, const char *name,
719 				enum sieve_error *error_r)
720 {
721 	struct sieve_script *script;
722 
723 	if (error_r != NULL)
724 		*error_r = SIEVE_ERROR_NONE;
725 	sieve_storage_clear_error(storage);
726 
727 	/* Validate script name */
728 	if (name != NULL && !sieve_script_name_is_valid(name)) {
729 		sieve_storage_set_error(storage,
730 			SIEVE_ERROR_BAD_PARAMS,
731 			"Invalid script name `%s'.",
732 			str_sanitize(name, 80));
733 		if (error_r != NULL)
734 			*error_r = storage->error_code;
735 		return NULL;
736 	}
737 
738 	i_assert(storage->v.get_script != NULL);
739 	script = storage->v.get_script(storage, name);
740 	return script;
741 }
742 
743 struct sieve_script *
sieve_storage_get_script(struct sieve_storage * storage,const char * name,enum sieve_error * error_r)744 sieve_storage_get_script(struct sieve_storage *storage, const char *name,
745 			 enum sieve_error *error_r)
746 {
747 	struct sieve_instance *svinst = storage->svinst;
748 	struct sieve_script *script;
749 
750 	script = sieve_storage_get_script_direct(storage, name, error_r);
751 	if (script == NULL) {
752 		/* Error */
753 		if (storage->error_code == SIEVE_ERROR_NOT_FOUND &&
754 		    (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 &&
755 		    storage->default_name != NULL &&
756 		    storage->default_location != NULL &&
757 		    strcmp(storage->default_name, name) == 0) {
758 			/* Not found; if this name maps to the default script,
759 			   try to access that instead */
760 			i_assert(*storage->default_location != '\0');
761 
762 			e_debug(storage->event,
763 				"Trying default script instead");
764 
765 			script = sieve_script_create(
766 				svinst,	storage->default_location, NULL,
767 				error_r);
768 			if (script != NULL) {
769 				script->storage->is_default = TRUE;
770 				script->storage->default_for = storage;
771 				sieve_storage_ref(storage);
772 			}
773 
774 		} else if (error_r != NULL) {
775 			*error_r = storage->error_code;
776 		}
777 	}
778 	return script;
779 }
780 
781 struct sieve_script *
sieve_storage_open_script(struct sieve_storage * storage,const char * name,enum sieve_error * error_r)782 sieve_storage_open_script(struct sieve_storage *storage, const char *name,
783 			  enum sieve_error *error_r)
784 {
785 	struct sieve_instance *svinst = storage->svinst;
786 	struct sieve_script *script;
787 
788 	script = sieve_storage_get_script(storage, name, error_r);
789 	if (script == NULL)
790 		return NULL;
791 
792 	if (sieve_script_open(script, error_r) >= 0)
793 		return script;
794 
795 	/* Error */
796 	sieve_script_unref(&script);
797 	script = NULL;
798 
799 	if (storage->error_code == SIEVE_ERROR_NOT_FOUND &&
800 	    (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 &&
801 	    storage->default_name != NULL &&
802 	    storage->default_location != NULL &&
803 	    strcmp(storage->default_name, name) == 0) {
804 		/* Not found; if this name maps to the default script,
805 		   try to open that instead */
806 		i_assert(*storage->default_location != '\0');
807 
808 		e_debug(storage->event, "Trying default script instead");
809 
810 		script = sieve_script_create_open(
811 			svinst, storage->default_location, NULL, error_r);
812 		if (script != NULL) {
813 			script->storage->is_default = TRUE;
814 			script->storage->default_for = storage;
815 			sieve_storage_ref(storage);
816 		}
817 	}
818 	return script;
819 }
820 
821 static int
sieve_storage_check_script_direct(struct sieve_storage * storage,const char * name,enum sieve_error * error_r)822 sieve_storage_check_script_direct(struct sieve_storage *storage,
823 				  const char *name, enum sieve_error *error_r)
824 				  ATTR_NULL(3)
825 {
826 	struct sieve_script *script;
827 	enum sieve_error error;
828 	int ret;
829 
830 	if (error_r == NULL)
831 		error_r = &error;
832 
833 	script = sieve_storage_get_script_direct(storage, name, error_r);
834 	if (script == NULL)
835 		return (*error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1);
836 
837 	ret = sieve_script_open(script, error_r);
838 	sieve_script_unref(&script);
839 	return (ret >= 0 ? 1 : (*error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1));
840 }
841 
sieve_storage_check_script(struct sieve_storage * storage,const char * name,enum sieve_error * error_r)842 int sieve_storage_check_script(struct sieve_storage *storage, const char *name,
843 			       enum sieve_error *error_r)
844 {
845 	struct sieve_script *script;
846 	enum sieve_error error;
847 
848 	if (error_r == NULL)
849 		error_r = &error;
850 
851 	script = sieve_storage_open_script(storage, name, error_r);
852 	if (script == NULL)
853 		return (*error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1);
854 
855 	sieve_script_unref(&script);
856 	return 1;
857 }
858 
859 /*
860  * Script sequence
861  */
862 
863 struct sieve_script_sequence *
sieve_storage_get_script_sequence(struct sieve_storage * storage,enum sieve_error * error_r)864 sieve_storage_get_script_sequence(struct sieve_storage *storage,
865 				  enum sieve_error *error_r)
866 {
867 	enum sieve_error error;
868 
869 	if (error_r != NULL)
870 		*error_r = SIEVE_ERROR_NONE;
871 	else
872 		error_r = &error;
873 
874 	i_assert(storage->v.get_script_sequence != NULL);
875 	return storage->v.get_script_sequence(storage, error_r);
876 }
877 
878 /*
879  * Active script
880  */
881 
882 static int
sieve_storage_active_script_do_get_name(struct sieve_storage * storage,const char ** name_r,bool * default_r)883 sieve_storage_active_script_do_get_name(struct sieve_storage *storage,
884 					const char **name_r, bool *default_r)
885 					ATTR_NULL(3)
886 {
887 	struct sieve_instance *svinst = storage->svinst;
888 	enum sieve_error error;
889 	int ret;
890 
891 	if (default_r != NULL)
892 		*default_r = FALSE;
893 
894 	i_assert(storage->v.active_script_get_name != NULL);
895 	ret = storage->v.active_script_get_name(storage, name_r);
896 
897 	if (ret != 0 ||
898 	    (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 ||
899 	    storage->default_location == NULL ||
900 	    storage->default_name == NULL) {
901 		return ret;
902 	}
903 
904 	*name_r = storage->default_name;
905 
906 	ret = sieve_script_check(svinst, storage->default_location,
907 				 NULL, &error);
908 	if (ret <= 0)
909 		return ret;
910 
911 	if (default_r != NULL)
912 		*default_r = TRUE;
913 	return 1;
914 }
915 
sieve_storage_active_script_get_name(struct sieve_storage * storage,const char ** name_r)916 int sieve_storage_active_script_get_name(struct sieve_storage *storage,
917 					 const char **name_r)
918 {
919 	return sieve_storage_active_script_do_get_name(storage, name_r, NULL);
920 }
921 
sieve_storage_active_script_is_default(struct sieve_storage * storage)922 int sieve_storage_active_script_is_default(struct sieve_storage *storage)
923 {
924 	const char *name;
925 	bool is_default = FALSE;
926 	int ret;
927 
928 	ret = sieve_storage_active_script_do_get_name(storage, &name,
929 						      &is_default);
930 	return (ret < 0 ? -1 : (is_default ? 1 : 0));
931 }
932 
933 struct sieve_script *
sieve_storage_active_script_open(struct sieve_storage * storage,enum sieve_error * error_r)934 sieve_storage_active_script_open(struct sieve_storage *storage,
935 				 enum sieve_error *error_r)
936 {
937 	struct sieve_instance *svinst = storage->svinst;
938 	struct sieve_script *script;
939 
940 	i_assert(storage->v.active_script_open != NULL);
941 	script = storage->v.active_script_open(storage);
942 
943 	if (script != NULL ||
944 	    (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 ||
945 	    storage->default_location == NULL) {
946 		if (error_r != NULL)
947 			*error_r = storage->error_code;
948 		return script;
949 	}
950 
951 	/* Try default script location */
952 	script = sieve_script_create_open(svinst, storage->default_location,
953 					  NULL, error_r);
954 	if (script != NULL) {
955 		script->storage->is_default = TRUE;
956 		script->storage->default_for = storage;
957 		sieve_storage_ref(storage);
958 	}
959 	return script;
960 }
961 
sieve_storage_deactivate(struct sieve_storage * storage,time_t mtime)962 int sieve_storage_deactivate(struct sieve_storage *storage, time_t mtime)
963 {
964 	int ret;
965 
966 	i_assert((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0);
967 
968 	i_assert(storage->v.deactivate != NULL);
969 	ret = storage->v.deactivate(storage);
970 
971 	if (ret >= 0) {
972 		struct event_passthrough *e =
973 			event_create_passthrough(storage->event)->
974 			set_name("sieve_storage_deactivated");
975 		e_debug(e->event(), "Storage activated");
976 
977 		sieve_storage_set_modified(storage, mtime);
978 		(void)sieve_storage_sync_deactivate(storage);
979 	} else {
980 		struct event_passthrough *e =
981 			event_create_passthrough(storage->event)->
982 			add_str("error", storage->error)->
983 			set_name("sieve_storage_deactivated");
984 		e_debug(e->event(), "Failed to deactivate storage: %s",
985 			storage->error);
986 	}
987 
988 	return ret;
989 }
990 
sieve_storage_active_script_get_last_change(struct sieve_storage * storage,time_t * last_change_r)991 int sieve_storage_active_script_get_last_change(struct sieve_storage *storage,
992 						time_t *last_change_r)
993 {
994 	i_assert(storage->v.active_script_get_last_change != NULL);
995 
996 	return storage->v.active_script_get_last_change(storage, last_change_r);
997 }
998 
999 /*
1000  * Listing scripts
1001  */
1002 
1003 struct sieve_storage_list_context *
sieve_storage_list_init(struct sieve_storage * storage)1004 sieve_storage_list_init(struct sieve_storage *storage)
1005 {
1006 	struct sieve_storage_list_context *lctx;
1007 
1008 	i_assert(storage->v.list_init != NULL);
1009 	lctx = storage->v.list_init(storage);
1010 
1011 	if (lctx != NULL)
1012 		lctx->storage = storage;
1013 
1014 	return lctx;
1015 }
1016 
1017 const char *
sieve_storage_list_next(struct sieve_storage_list_context * lctx,bool * active_r)1018 sieve_storage_list_next(struct sieve_storage_list_context *lctx, bool *active_r)
1019 {
1020 	struct sieve_storage *storage = lctx->storage;
1021 	struct sieve_instance *svinst = storage->svinst;
1022 	const char *scriptname;
1023 	bool have_default, script_active = FALSE;
1024 
1025 	have_default = (storage->default_name != NULL &&
1026 			storage->default_location != NULL &&
1027 			(storage->flags &
1028 			 SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0);
1029 
1030 	i_assert(storage->v.list_next != NULL);
1031 	scriptname = storage->v.list_next(lctx, &script_active);
1032 
1033 	i_assert(!script_active || !lctx->seen_active);
1034 	if (script_active)
1035 		lctx->seen_active = TRUE;
1036 
1037 	if (scriptname != NULL) {
1038 		/* Remember when we see that the storage has its own script for
1039 		   default */
1040 		if (have_default &&
1041 		    strcmp(scriptname, storage->default_name) == 0)
1042 			lctx->seen_default = TRUE;
1043 
1044 	} else if (have_default && !lctx->seen_default &&
1045 		sieve_script_check(svinst, storage->default_location,
1046 				   NULL, NULL) > 0) {
1047 
1048 		/* Return default script at the end if it was not listed
1049 		   thus far (storage backend has no script under default
1050 		   name) */
1051 		scriptname = storage->default_name;
1052 		lctx->seen_default = TRUE;
1053 
1054 		/* Mark default as active if no normal script is active */
1055 		if (!lctx->seen_active) {
1056 			script_active = TRUE;
1057 			lctx->seen_active = TRUE;
1058 		}
1059 	}
1060 
1061 	if (active_r != NULL)
1062 		*active_r = script_active;
1063 	return scriptname;
1064 }
1065 
sieve_storage_list_deinit(struct sieve_storage_list_context ** _lctx)1066 int sieve_storage_list_deinit(struct sieve_storage_list_context **_lctx)
1067 {
1068 	struct sieve_storage_list_context *lctx = *_lctx;
1069 	struct sieve_storage *storage = lctx->storage;
1070 	int ret;
1071 
1072 	i_assert(storage->v.list_deinit != NULL);
1073 	ret = storage->v.list_deinit(lctx);
1074 
1075 	*_lctx = NULL;
1076 	return ret;
1077 }
1078 
1079 /*
1080  * Saving scripts
1081  */
1082 
1083 static struct event *
sieve_storage_save_create_event(struct sieve_storage * storage,const char * scriptname)1084 sieve_storage_save_create_event(struct sieve_storage *storage,
1085 				const char *scriptname) ATTR_NULL(2)
1086 {
1087 	struct event *event;
1088 
1089 	event = event_create(storage->event);
1090 	event_add_str(event, "script_name", scriptname);
1091 	if (scriptname == NULL) {
1092 		event_set_append_log_prefix(event, "save: ");
1093 	} else {
1094 		event_set_append_log_prefix(
1095 			event, t_strdup_printf("script `%s': save: ",
1096 					       scriptname));
1097 	}
1098 
1099 	return event;
1100 }
1101 
sieve_storage_save_cleanup(struct sieve_storage_save_context * sctx)1102 static void sieve_storage_save_cleanup(struct sieve_storage_save_context *sctx)
1103 {
1104 	if (sctx->scriptobject != NULL)
1105 		sieve_script_unref(&sctx->scriptobject);
1106 }
1107 
sieve_storage_save_deinit(struct sieve_storage_save_context ** _sctx)1108 static void sieve_storage_save_deinit(struct sieve_storage_save_context **_sctx)
1109 {
1110 	struct sieve_storage_save_context *sctx = *_sctx;
1111 
1112 	*_sctx = NULL;
1113 	if (sctx == NULL)
1114 		return;
1115 
1116 	sieve_storage_save_cleanup(sctx);
1117 	event_unref(&sctx->event);
1118 	pool_unref(&sctx->pool);
1119 }
1120 
1121 struct sieve_storage_save_context *
sieve_storage_save_init(struct sieve_storage * storage,const char * scriptname,struct istream * input)1122 sieve_storage_save_init(struct sieve_storage *storage, const char *scriptname,
1123 			struct istream *input)
1124 {
1125 	struct sieve_storage_save_context *sctx;
1126 
1127 	if (scriptname != NULL) {
1128 		/* Validate script name */
1129 		if (!sieve_script_name_is_valid(scriptname)) {
1130 			sieve_storage_set_error(storage,
1131 				SIEVE_ERROR_BAD_PARAMS,
1132 				"Invalid Sieve script name `%s'.",
1133 				str_sanitize(scriptname, 80));
1134 			return NULL;
1135 		}
1136 	}
1137 
1138 	i_assert((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0);
1139 
1140 	i_assert(storage->v.save_alloc != NULL);
1141 	sctx = storage->v.save_alloc(storage);
1142 	sctx->storage = storage;
1143 
1144 	sctx->event = sieve_storage_save_create_event(storage, scriptname);
1145 
1146 	struct event_passthrough *e =
1147 		event_create_passthrough(sctx->event)->
1148 		set_name("sieve_storage_save_started");
1149 	e_debug(e->event(), "Started saving script");
1150 
1151 	i_assert(storage->v.save_init != NULL);
1152 	if ((storage->v.save_init(sctx, scriptname, input)) < 0) {
1153 		struct event_passthrough *e =
1154 			event_create_passthrough(sctx->event)->
1155 			add_str("error", storage->error)->
1156 			set_name("sieve_storage_save_finished");
1157 		e_debug(e->event(), "Failed to save script: %s",
1158 			storage->error);
1159 
1160 		sieve_storage_save_deinit(&sctx);
1161 		return NULL;
1162 	}
1163 
1164 	sctx->mtime = (time_t)-1;
1165 
1166 	i_assert(sctx->input != NULL);
1167 
1168 	return sctx;
1169 }
1170 
sieve_storage_save_continue(struct sieve_storage_save_context * sctx)1171 int sieve_storage_save_continue(struct sieve_storage_save_context *sctx)
1172 {
1173 	struct sieve_storage *storage = sctx->storage;
1174 	int ret;
1175 
1176 	i_assert(storage->v.save_continue != NULL);
1177 	ret = storage->v.save_continue(sctx);
1178 	if (ret < 0)
1179 		sctx->failed = TRUE;
1180 	return ret;
1181 }
1182 
sieve_storage_save_finish(struct sieve_storage_save_context * sctx)1183 int sieve_storage_save_finish(struct sieve_storage_save_context *sctx)
1184 {
1185 	struct sieve_storage *storage = sctx->storage;
1186 	int ret;
1187 
1188 	i_assert(!sctx->finished);
1189 	sctx->finished = TRUE;
1190 
1191 	i_assert(storage->v.save_finish != NULL);
1192 	ret = storage->v.save_finish(sctx);
1193 	if (ret < 0) {
1194 		struct event_passthrough *e =
1195 			event_create_passthrough(sctx->event)->
1196 			add_str("error", storage->error)->
1197 			set_name("sieve_storage_save_finished");
1198 		e_debug(e->event(), "Failed to upload script: %s",
1199 			storage->error);
1200 
1201 		sctx->failed = TRUE;
1202 	}
1203 	return ret;
1204 }
1205 
sieve_storage_save_set_mtime(struct sieve_storage_save_context * sctx,time_t mtime)1206 void sieve_storage_save_set_mtime(struct sieve_storage_save_context *sctx,
1207 				  time_t mtime)
1208 {
1209 	sctx->mtime = mtime;
1210 }
1211 
1212 struct sieve_script *
sieve_storage_save_get_tempscript(struct sieve_storage_save_context * sctx)1213 sieve_storage_save_get_tempscript(struct sieve_storage_save_context *sctx)
1214 {
1215 	struct sieve_storage *storage = sctx->storage;
1216 
1217 	if (sctx->failed)
1218 		return NULL;
1219 
1220 	if (sctx->scriptobject != NULL)
1221 		return sctx->scriptobject;
1222 
1223 	i_assert(storage->v.save_get_tempscript != NULL);
1224 	sctx->scriptobject = storage->v.save_get_tempscript(sctx);
1225 
1226 	i_assert(sctx->scriptobject != NULL ||
1227 		 storage->error_code != SIEVE_ERROR_NONE);
1228 	return sctx->scriptobject;
1229 }
1230 
sieve_storage_save_will_activate(struct sieve_storage_save_context * sctx)1231 bool sieve_storage_save_will_activate(struct sieve_storage_save_context *sctx)
1232 {
1233 	if (sctx->scriptname == NULL)
1234 		return FALSE;
1235 
1236 	if (sctx->active_scriptname == NULL) {
1237 		const char *scriptname;
1238 
1239 		if (sieve_storage_active_script_get_name(sctx->storage,
1240 							 &scriptname) > 0) {
1241 			sctx->active_scriptname =
1242 				p_strdup(sctx->pool, scriptname);
1243 		}
1244 	}
1245 
1246  	/* Is the requested script active? */
1247 	return (sctx->active_scriptname != NULL &&
1248 		strcmp(sctx->scriptname, sctx->active_scriptname) == 0);
1249 }
1250 
sieve_storage_save_commit(struct sieve_storage_save_context ** _sctx)1251 int sieve_storage_save_commit(struct sieve_storage_save_context **_sctx)
1252 {
1253 	struct sieve_storage_save_context *sctx = *_sctx;
1254 	struct sieve_storage *storage;
1255 	const char *scriptname;
1256 	bool default_activate = FALSE;
1257 	int ret;
1258 
1259 	*_sctx = NULL;
1260 	if (sctx == NULL)
1261 		return 0;
1262 
1263 	storage = sctx->storage;
1264 	scriptname = sctx->scriptname;
1265 
1266 	i_assert(!sctx->failed);
1267 	i_assert(sctx->finished);
1268 	i_assert(sctx->scriptname != NULL);
1269 
1270 	/* Check whether we're replacing the default active script */
1271 	if (storage->default_name != NULL &&
1272 	    storage->default_location != NULL &&
1273 	    (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 &&
1274 	    strcmp(sctx->scriptname, storage->default_name) == 0 &&
1275 	    sieve_storage_save_will_activate(sctx) &&
1276 	    sieve_storage_check_script_direct(storage, storage->default_name,
1277 					      NULL) <= 0)
1278 		default_activate = TRUE;
1279 
1280 	sieve_storage_save_cleanup(sctx);
1281 
1282 	i_assert(storage->v.save_commit != NULL);
1283 	ret = storage->v.save_commit(sctx);
1284 
1285 	/* Implicitly activate it when we're replacing the default
1286 	   active script */
1287 	if (ret >= 0 && default_activate) {
1288 		struct sieve_script *script;
1289 		enum sieve_error error;
1290 
1291 		script = sieve_storage_open_script(storage, scriptname, &error);
1292 		if (script == NULL) {
1293 			/* Somehow not actually saved */
1294 			ret = (error == SIEVE_ERROR_NOT_FOUND ? 0 : -1);
1295 		} else if (sieve_script_activate(script, (time_t)-1) < 0) {
1296 			/* Failed to activate; roll back */
1297 			ret = -1;
1298 			(void)sieve_script_delete(script, TRUE);
1299 		}
1300 		if (script != NULL)
1301 			sieve_script_unref(&script);
1302 
1303 		if (ret < 0) {
1304 			e_error(sctx->event,
1305 				"Failed to implicitly activate script `%s' "
1306 				"while replacing the default active script",
1307 				scriptname);
1308 		}
1309 	}
1310 
1311 	if (ret >= 0) {
1312 		struct event_passthrough *e =
1313 			event_create_passthrough(sctx->event)->
1314 			set_name("sieve_storage_save_finished");
1315 		e_debug(e->event(), "Finished saving script");
1316 
1317 		/* set INBOX mailbox attribute */
1318 		(void)sieve_storage_sync_script_save(storage, scriptname);
1319 	} else {
1320 		struct event_passthrough *e =
1321 			event_create_passthrough(sctx->event)->
1322 			add_str("error", storage->error)->
1323 			set_name("sieve_storage_save_finished");
1324 
1325 		e_debug(e->event(), "Failed to save script: %s",
1326 			storage->error);
1327 	}
1328 
1329 	sieve_storage_save_deinit(&sctx);
1330 	return ret;
1331 }
1332 
sieve_storage_save_cancel(struct sieve_storage_save_context ** _sctx)1333 void sieve_storage_save_cancel(struct sieve_storage_save_context **_sctx)
1334 {
1335 	struct sieve_storage_save_context *sctx = *_sctx;
1336 	struct sieve_storage *storage;
1337 
1338 	*_sctx = NULL;
1339 	if (sctx == NULL)
1340 		return;
1341 
1342 	storage = sctx->storage;
1343 
1344 	sctx->failed = TRUE;
1345 
1346 	sieve_storage_save_cleanup(sctx);
1347 
1348 	if (!sctx->finished)
1349 		(void)sieve_storage_save_finish(sctx);
1350 
1351 	struct event_passthrough *e =
1352 		event_create_passthrough(sctx->event)->
1353 		add_str("error", "Canceled")->
1354 		set_name("sieve_storage_save_finished");
1355 	e_debug(e->event(), "Canceled saving script");
1356 
1357 	i_assert(storage->v.save_cancel != NULL);
1358 	storage->v.save_cancel(sctx);
1359 
1360 	sieve_storage_save_deinit(&sctx);
1361 }
1362 
sieve_storage_save_as_active(struct sieve_storage * storage,struct istream * input,time_t mtime)1363 int sieve_storage_save_as_active(struct sieve_storage *storage,
1364 				 struct istream *input, time_t mtime)
1365 {
1366 	struct event *event;
1367 	int ret;
1368 
1369 	event = event_create(storage->event);
1370 	event_set_append_log_prefix(event, "active script: save: ");
1371 
1372 	struct event_passthrough *e =
1373 		event_create_passthrough(event)->
1374 		set_name("sieve_storage_save_started");
1375 	e_debug(e->event(), "Started saving active script");
1376 
1377 	i_assert(storage->v.save_as_active != NULL);
1378 	ret = storage->v.save_as_active(storage, input, mtime);
1379 
1380 	if (ret >= 0) {
1381 		struct event_passthrough *e =
1382 			event_create_passthrough(event)->
1383 			set_name("sieve_storage_save_finished");
1384 		e_debug(e->event(), "Finished saving active script");
1385 	} else {
1386 		struct event_passthrough *e =
1387 			event_create_passthrough(event)->
1388 			add_str("error", storage->error)->
1389 			set_name("sieve_storage_save_finished");
1390 		e_debug(e->event(), "Failed to save active script: %s",
1391 			storage->error);
1392 	}
1393 
1394 	event_unref(&event);
1395 	return ret;
1396 }
1397 
sieve_storage_save_as(struct sieve_storage * storage,struct istream * input,const char * name)1398 int sieve_storage_save_as(struct sieve_storage *storage, struct istream *input,
1399 			  const char *name)
1400 {
1401 	struct event *event;
1402 	int ret;
1403 
1404 	event = sieve_storage_save_create_event(storage, name);
1405 
1406 	struct event_passthrough *e =
1407 		event_create_passthrough(event)->
1408 		set_name("sieve_storage_save_started");
1409 	e_debug(e->event(), "Started saving script");
1410 
1411 	i_assert(storage->v.save_as != NULL);
1412 	ret = storage->v.save_as(storage, input, name);
1413 
1414 	if (ret >= 0) {
1415 		struct event_passthrough *e =
1416 			event_create_passthrough(event)->
1417 			set_name("sieve_storage_save_finished");
1418 		e_debug(e->event(), "Finished saving sieve script");
1419 	} else {
1420 		struct event_passthrough *e =
1421 			event_create_passthrough(event)->
1422 			add_str("error", storage->error)->
1423 			set_name("sieve_storage_save_finished");
1424 		e_debug(e->event(), "Failed to save script: %s",
1425 			storage->error);
1426 	}
1427 
1428 	event_unref(&event);
1429 	return ret;
1430 }
1431 
1432 /*
1433  * Checking quota
1434  */
1435 
sieve_storage_quota_validsize(struct sieve_storage * storage,size_t size,uint64_t * limit_r)1436 bool sieve_storage_quota_validsize(struct sieve_storage *storage, size_t size,
1437 				   uint64_t *limit_r)
1438 {
1439 	uint64_t max_size;
1440 
1441 	max_size = sieve_max_script_size(storage->svinst);
1442 	if (max_size > 0 && size > max_size) {
1443 		*limit_r = max_size;
1444 		return FALSE;
1445 	}
1446 
1447 	return TRUE;
1448 }
1449 
sieve_storage_quota_max_script_size(struct sieve_storage * storage)1450 uint64_t sieve_storage_quota_max_script_size(struct sieve_storage *storage)
1451 {
1452 	return sieve_max_script_size(storage->svinst);
1453 }
1454 
sieve_storage_quota_havespace(struct sieve_storage * storage,const char * scriptname,size_t size,enum sieve_storage_quota * quota_r,uint64_t * limit_r)1455 int sieve_storage_quota_havespace(struct sieve_storage *storage,
1456 				  const char *scriptname, size_t size,
1457 				  enum sieve_storage_quota *quota_r,
1458 				  uint64_t *limit_r)
1459 {
1460 	*quota_r = SIEVE_STORAGE_QUOTA_NONE;
1461 	*limit_r = 0;
1462 
1463 	/* Check the script size */
1464 	if (!sieve_storage_quota_validsize(storage, size, limit_r)) {
1465 		*quota_r = SIEVE_STORAGE_QUOTA_MAXSIZE;
1466 		return 0;
1467 	}
1468 
1469 	/* Do we need to scan the storage (quota enabled) ? */
1470 	if (storage->max_scripts == 0 && storage->max_storage == 0)
1471 		return 1;
1472 
1473 	if (storage->v.quota_havespace == NULL)
1474 		return 1;
1475 
1476 	return storage->v.quota_havespace(storage, scriptname, size,
1477 					  quota_r, limit_r);
1478 }
1479 
1480 /*
1481  * Properties
1482  */
1483 
sieve_storage_location(const struct sieve_storage * storage)1484 const char *sieve_storage_location(const struct sieve_storage *storage)
1485 {
1486 	return storage->location;
1487 }
1488 
sieve_storage_is_default(const struct sieve_storage * storage)1489 bool sieve_storage_is_default(const struct sieve_storage *storage)
1490 {
1491 	return storage->is_default;
1492 }
1493 
1494 /*
1495  * Error handling
1496  */
1497 
sieve_storage_clear_error(struct sieve_storage * storage)1498 void sieve_storage_clear_error(struct sieve_storage *storage)
1499 {
1500 	i_free(storage->error);
1501 	storage->error_code = SIEVE_ERROR_NONE;
1502 	storage->error = NULL;
1503 }
1504 
sieve_storage_set_error(struct sieve_storage * storage,enum sieve_error error,const char * fmt,...)1505 void sieve_storage_set_error(struct sieve_storage *storage,
1506 			     enum sieve_error error, const char *fmt, ...)
1507 {
1508 	va_list va;
1509 
1510 	sieve_storage_clear_error(storage);
1511 
1512 	if (fmt != NULL) {
1513 		va_start(va, fmt);
1514 		storage->error = i_strdup_vprintf(fmt, va);
1515 		va_end(va);
1516 	}
1517 
1518 	storage->error_code = error;
1519 }
1520 
sieve_storage_copy_error(struct sieve_storage * storage,const struct sieve_storage * source)1521 void sieve_storage_copy_error(struct sieve_storage *storage,
1522 			      const struct sieve_storage *source)
1523 {
1524 	sieve_storage_clear_error(storage);
1525 	storage->error = i_strdup(source->error);
1526 	storage->error_code = source->error_code;
1527 }
1528 
sieve_storage_set_internal_error(struct sieve_storage * storage)1529 void sieve_storage_set_internal_error(struct sieve_storage *storage)
1530 {
1531 	struct tm *tm;
1532 	char str[256];
1533 
1534 	sieve_storage_clear_error(storage);
1535 
1536 	/* critical errors may contain sensitive data, so let user
1537 	   see only "Internal error" with a timestamp to make it
1538 	   easier to look from log files the actual error message. */
1539 	tm = localtime(&ioloop_time);
1540 
1541 	storage->error =
1542 		(strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ?
1543 		 i_strdup(str) : i_strdup(CRITICAL_MSG));
1544 
1545 	storage->error_code = SIEVE_ERROR_TEMP_FAILURE;
1546 }
1547 
sieve_storage_set_critical(struct sieve_storage * storage,const char * fmt,...)1548 void sieve_storage_set_critical(struct sieve_storage *storage,
1549 				const char *fmt, ...)
1550 {
1551 	va_list va;
1552 
1553 	if (fmt != NULL) {
1554 		if ((storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0) {
1555 			va_start(va, fmt);
1556 			e_error(storage->svinst->event, "%s storage: %s",
1557 				storage->driver_name,
1558 				t_strdup_vprintf(fmt, va));
1559 			va_end(va);
1560 
1561 			sieve_storage_set_internal_error(storage);
1562 
1563 		} else {
1564 			sieve_storage_clear_error(storage);
1565 
1566 			/* no user is involved while synchronizing, so do it the
1567 			   normal way */
1568 			va_start(va, fmt);
1569 			storage->error = i_strdup_vprintf(fmt, va);
1570 			va_end(va);
1571 
1572 			storage->error_code = SIEVE_ERROR_TEMP_FAILURE;
1573 		}
1574 	}
1575 }
1576 
1577 const char *
sieve_storage_get_last_error(struct sieve_storage * storage,enum sieve_error * error_r)1578 sieve_storage_get_last_error(struct sieve_storage *storage,
1579 			     enum sieve_error *error_r)
1580 {
1581 	/* We get here only in error situations, so we have to return some
1582 	   error. If storage->error is NULL, it means we forgot to set it at
1583 	   some point..
1584 	 */
1585 
1586 	if (error_r != NULL)
1587 		*error_r = storage->error_code;
1588 
1589 	return storage->error != NULL ? storage->error : "Unknown error";
1590 }
1591