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(®->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(®->storage_classes, &count);
89 for (i = 0; i < count; i++) {
90 if (classes[i] == storage_class) {
91 array_delete(®->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(®->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