#include "nfs-workarounds.h"
#include "settings.h"
#include "mailbox-list-private.h"
-#include "acl-global-file.h"
#include "acl-cache.h"
#include "acl-backend-vfile.h"
}
static int
-acl_backend_vfile_init(struct acl_backend *_backend, const char **error_r)
+acl_backend_vfile_init(struct acl_backend *_backend, const char **error_r ATTR_UNUSED)
{
- struct event *event = _backend->event;
- struct stat st;
-
- const char *global_path = _backend->set->acl_global_path;
-
- if (*global_path != '\0') {
- if (stat(global_path, &st) < 0) {
- *error_r = t_strdup_printf("stat(%s) failed: %m", global_path);
- return -1;
- } else if (S_ISDIR(st.st_mode)) {
- *error_r = t_strdup_printf("Global ACL directories are no longer supported");
- return -1;
- } else {
- _backend->global_file = acl_global_file_init(
- global_path, _backend->set->acl_cache_ttl / 1000, event);
- e_debug(event, "vfile: Deprecated Global ACL file: %s", global_path);
- }
- }
-
_backend->cache =
acl_cache_init(_backend,
sizeof(struct acl_backend_vfile_validity));
array_free(&backend->acllist);
pool_unref(&backend->acllist_pool);
}
- if (_backend->global_file != NULL)
- acl_global_file_deinit(&_backend->global_file);
pool_unref(&backend->backend.pool);
}
struct mailbox *box =
mailbox_alloc(_backend->list, vname,
MAILBOX_FLAG_READONLY | MAILBOX_FLAG_IGNORE_ACLS);
- if (_backend->global_file != NULL) {
- /* check global ACL file */
- ret = acl_global_file_refresh(_backend->global_file);
- if (ret == 0 && acl_global_file_have_any(_backend->global_file, box->vname))
- ret = 1;
- } else {
- /* global ACLs disabled */
- ret = 0;
- }
-
- if (ret != 0) {
- /* error / global ACL found */
- } else if (mailbox_open(box) == 0) {
+ if (mailbox_open(box) == 0) {
/* mailbox exists */
ret = 1;
} else {
if (validity->local_validity.last_mtime != 0)
*mtime_r = validity->local_validity.last_mtime;
- else if (validity->global_validity.last_mtime != 0)
- *mtime_r = validity->global_validity.last_mtime;
else
*mtime_r = 0;
return 0;
}
-static int
-acl_backend_global_file_refresh(struct acl_object *_aclobj,
- struct acl_vfile_validity *validity)
-{
- struct acl_backend_vfile *backend =
- container_of(_aclobj->backend, struct acl_backend_vfile, backend);
- struct stat st;
-
- if (acl_global_file_refresh(_aclobj->backend->global_file) < 0)
- return -1;
-
- acl_global_file_last_stat(_aclobj->backend->global_file, &st);
- if (validity == NULL)
- return 1;
- return acl_vfile_validity_has_changed(backend, validity, &st) ? 1 : 0;
-}
-
static int acl_backend_vfile_object_refresh_cache(struct acl_object *_aclobj)
{
struct acl_object_vfile *aclobj =
struct acl_backend_vfile_validity *old_validity;
struct acl_backend_vfile_validity validity;
time_t mtime;
- int ret = 0;
+ int ret;
old_validity = acl_cache_get_validity(_aclobj->backend->cache,
_aclobj->name);
- if (_aclobj->backend->global_file != NULL)
- ret = acl_backend_global_file_refresh(_aclobj, old_validity == NULL ? NULL :
- &old_validity->global_validity);
- if (ret == 0) {
- ret = acl_backend_vfile_refresh(_aclobj, aclobj->local_path,
- old_validity == NULL ? NULL :
- &old_validity->local_validity);
- }
+ ret = acl_backend_vfile_refresh(_aclobj, aclobj->local_path,
+ old_validity == NULL ? NULL :
+ &old_validity->local_validity);
if (ret <= 0)
return ret;
}
i_zero(&validity);
- if (_aclobj->backend->global_file != NULL) {
- struct stat st;
-
- acl_object_add_global_acls(_aclobj);
- acl_global_file_last_stat(_aclobj->backend->global_file, &st);
- validity.global_validity.last_read_time = ioloop_time;
- validity.global_validity.last_mtime = st.st_mtime;
- validity.global_validity.last_size = st.st_size;
- }
-
if (acl_backend_get_mailbox_acl(_aclobj->backend, _aclobj) < 0)
return -1;
+++ /dev/null
-/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "array.h"
-#include "ioloop.h"
-#include "istream.h"
-#include "strescape.h"
-#include "wildcard-match.h"
-#include "acl-api-private.h"
-#include "acl-global-file.h"
-
-#include <sys/stat.h>
-
-struct acl_global_rights {
- const char *vpattern;
- ARRAY_TYPE(acl_rights) rights;
-};
-
-struct acl_global_parse_rights {
- const char *vpattern;
- struct acl_rights rights;
-};
-
-struct acl_global_file {
- char *path;
- struct stat prev_st;
- struct event *event;
- time_t last_refresh_time;
-
- pool_t rights_pool;
- ARRAY(struct acl_global_rights) rights;
-
- unsigned int refresh_interval_secs;
-};
-
-struct acl_global_file *
-acl_global_file_init(const char *path, unsigned int refresh_interval_secs,
- struct event *event)
-{
- struct acl_global_file *file;
-
- file = i_new(struct acl_global_file, 1);
- file->path = i_strdup(path);
- file->refresh_interval_secs = refresh_interval_secs;
- file->event = event_create(event);
- i_array_init(&file->rights, 32);
- file->rights_pool = pool_alloconly_create("acl global file rights", 1024);
- return file;
-}
-
-void acl_global_file_deinit(struct acl_global_file **_file)
-{
- struct acl_global_file *file = *_file;
-
- if (file == NULL)
- return;
- *_file = NULL;
-
- array_free(&file->rights);
- event_unref(&file->event);
- pool_unref(&file->rights_pool);
- i_free(file->path);
- i_free(file);
-}
-
-static int acl_global_parse_rights_cmp(const struct acl_global_parse_rights *r1,
- const struct acl_global_parse_rights *r2)
-{
- return strcmp(r1->vpattern, r2->vpattern);
-}
-
-struct acl_global_file_parse_ctx {
- struct acl_global_file *file;
- ARRAY(struct acl_global_parse_rights) parse_rights;
-};
-
-static int
-acl_global_file_parse_line(struct acl_global_file_parse_ctx *ctx,
- const char *line, const char **error_r)
-{
- struct acl_global_parse_rights *pright;
- const char *p, *vpattern;
-
- if (*line == '"') {
- line++;
- if (str_unescape_next(&line, &vpattern) < 0) {
- *error_r = "Missing '\"'";
- return -1;
- }
- if (line[0] != ' ') {
- *error_r = "Expecting space after '\"'";
- return -1;
- }
- line++;
- } else {
- p = strchr(line, ' ');
- if (p == NULL) {
- *error_r = "Missing ACL rights";
- return -1;
- }
- if (p == line) {
- *error_r = "Empty ACL pattern";
- return -1;
- }
- vpattern = t_strdup_until(line, p);
- line = p + 1;
- }
-
- pright = array_append_space(&ctx->parse_rights);
- pright->vpattern = p_strdup(ctx->file->rights_pool, vpattern);
- if (acl_rights_parse_line(line, ctx->file->rights_pool,
- &pright->rights, error_r) < 0)
- return -1;
- pright->rights.global = TRUE;
- return 0;
-}
-
-static int acl_global_file_read(struct acl_global_file *file)
-{
- struct acl_global_file_parse_ctx ctx;
- struct acl_global_parse_rights *pright;
- struct acl_global_rights *right;
- struct istream *input;
- const char *line, *error, *prev_vpattern;
- unsigned int linenum = 0;
- int ret = 0;
-
- array_clear(&file->rights);
- p_clear(file->rights_pool);
-
- i_zero(&ctx);
- ctx.file = file;
- i_array_init(&ctx.parse_rights, 32);
-
- input = i_stream_create_file(file->path, SIZE_MAX);
- i_stream_set_return_partial_line(input, TRUE);
- while ((line = i_stream_read_next_line(input)) != NULL) {
- linenum++;
- if (line[0] == '\0' || line[0] == '#')
- continue;
- T_BEGIN {
- ret = acl_global_file_parse_line(&ctx, line, &error);
- if (ret < 0) {
- e_error(file->event,
- "Global ACL file %s line %u: %s",
- file->path, linenum, error);
- }
- } T_END;
- if (ret < 0)
- break;
- }
- if (ret == 0 && input->stream_errno != 0) {
- e_error(file->event,
- "Couldn't read global ACL file %s: %s",
- file->path, i_stream_get_error(input));
- ret = -1;
- }
- if (ret == 0) {
- const struct stat *st;
-
- if (i_stream_stat(input, TRUE, &st) < 0) {
- e_error(file->event,
- "Couldn't stat global ACL file %s: %s",
- file->path, i_stream_get_error(input));
- ret = -1;
- } else {
- file->prev_st = *st;
- }
- }
- i_stream_destroy(&input);
-
- /* sort all parsed rights */
- array_sort(&ctx.parse_rights, acl_global_parse_rights_cmp);
- /* combine identical patterns into same structs */
- prev_vpattern = ""; right = NULL;
- array_foreach_modifiable(&ctx.parse_rights, pright) {
- if (right == NULL ||
- strcmp(prev_vpattern, pright->vpattern) != 0) {
- right = array_append_space(&file->rights);
- right->vpattern = pright->vpattern;
- p_array_init(&right->rights, file->rights_pool, 4);
- }
- array_push_back(&right->rights, &pright->rights);
- }
-
- array_free(&ctx.parse_rights);
- return ret;
-}
-
-int acl_global_file_refresh(struct acl_global_file *file)
-{
- struct stat st;
-
- if (file->last_refresh_time + (time_t)file->refresh_interval_secs > ioloop_time)
- return 0;
- if (file->last_refresh_time != 0) {
- if (stat(file->path, &st) < 0) {
- e_error(file->event, "stat(%s) failed: %m", file->path);
- return -1;
- }
- if (st.st_ino == file->prev_st.st_ino &&
- st.st_size == file->prev_st.st_size &&
- CMP_ST_MTIME(&st, &file->prev_st)) {
- /* no change to the file */
- file->last_refresh_time = ioloop_time;
- return 0;
- }
- }
- if (acl_global_file_read(file) < 0)
- return -1;
- file->last_refresh_time = ioloop_time;
- return 0;
-}
-
-void acl_global_file_last_stat(struct acl_global_file *file, struct stat *st_r)
-{
- *st_r = file->prev_st;
-}
-
-void acl_global_file_get(struct acl_global_file *file, const char *vname,
- pool_t pool, ARRAY_TYPE(acl_rights) *rights_r)
-{
- struct acl_global_rights *global_rights;
- const struct acl_rights *rights;
- struct acl_rights *new_rights;
-
- array_foreach_modifiable(&file->rights, global_rights) {
- if (!wildcard_match(vname, global_rights->vpattern))
- continue;
- e_debug(file->event, "Mailbox '%s' matches global ACL pattern '%s'",
- vname, global_rights->vpattern);
- array_foreach(&global_rights->rights, rights) {
- new_rights = array_append_space(rights_r);
- acl_rights_dup(rights, pool, new_rights);
- }
- }
-}
-
-bool acl_global_file_have_any(struct acl_global_file *file, const char *vname)
-{
- struct acl_global_rights *rights;
-
- i_assert(file->last_refresh_time != 0);
-
- array_foreach_modifiable(&file->rights, rights) {
- if (wildcard_match(vname, rights->vpattern))
- return TRUE;
- }
- return FALSE;
-}