Mercurial > dovecot > core-2.2
changeset 22582:954ccfeef2f4
acl: Fix checking create (k) permission in global acl-file
Just because the global ACL file hasn't changed since it was last refreshed
for another ACL object, it doesn't mean that those ACLs don't need to be
applied to this ACL object.
This didn't usually cause problems, because the initial ACL object refresh
was always done due to local-path refresh returning "needs a refresh".
The only exception was when acl_object_init_from_parent() was called,
because it added an empty non-NULL validity for the local-path, so the
"needs a refresh" wasn't returned. This happened only when trying to
CREATE or RENAME mailbox under a parent where user didn't have create
permissions.
This affected only when using a single global acl-file, not when using
global acl directory containing per-mailbox files.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Fri, 06 Oct 2017 16:55:28 +0300 |
parents | 55a7f5a381cd |
children | 21c8f6efa1e3 |
files | src/plugins/acl/acl-backend-vfile.c src/plugins/acl/acl-global-file.c src/plugins/acl/acl-global-file.h |
diffstat | 3 files changed, 34 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/plugins/acl/acl-backend-vfile.c Fri Oct 06 16:54:20 2017 +0300 +++ b/src/plugins/acl/acl-backend-vfile.c Fri Oct 06 16:55:28 2017 +0300 @@ -532,6 +532,23 @@ return 0; } +static int +acl_backend_global_file_refresh(struct acl_object *_aclobj, + struct acl_vfile_validity *validity) +{ + struct acl_backend_vfile *backend = + (struct acl_backend_vfile *)_aclobj->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_object_vfile *)_aclobj; @@ -545,7 +562,8 @@ old_validity = acl_cache_get_validity(_aclobj->backend->cache, _aclobj->name); ret = _aclobj->backend->global_file != NULL ? - acl_global_file_refresh(_aclobj->backend->global_file) : + acl_backend_global_file_refresh(_aclobj, old_validity == NULL ? NULL : + &old_validity->global_validity) : acl_backend_vfile_refresh(_aclobj, aclobj->global_path, old_validity == NULL ? NULL : &old_validity->global_validity); @@ -568,9 +586,15 @@ } i_zero(&validity); - if (_aclobj->backend->global_file != NULL) + if (_aclobj->backend->global_file != NULL) { + struct stat st; + acl_object_add_global_acls(_aclobj); - else { + 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; + } else { if (acl_backend_vfile_read_with_retry(_aclobj, TRUE, aclobj->global_path, &validity.global_validity) < 0) return -1;
--- a/src/plugins/acl/acl-global-file.c Fri Oct 06 16:54:20 2017 +0300 +++ b/src/plugins/acl/acl-global-file.c Fri Oct 06 16:55:28 2017 +0300 @@ -203,6 +203,11 @@ 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) {
--- a/src/plugins/acl/acl-global-file.h Fri Oct 06 16:54:20 2017 +0300 +++ b/src/plugins/acl/acl-global-file.h Fri Oct 06 16:55:28 2017 +0300 @@ -10,6 +10,8 @@ /* Read the global ACLs into memory. */ int acl_global_file_refresh(struct acl_global_file *file); +/* Return stat data for the last refresh. */ +void acl_global_file_last_stat(struct acl_global_file *file, struct stat *st_r); /* Return global ACL rights matching the mailbox name. The file must already have been refreshed at least once. */