dovecot-2.2: acl plugin: Added an alternative global ACL file th...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Jan 27 16:36:11 EET 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/9376bf098692
changeset: 17118:9376bf098692
user: Timo Sirainen <tss at iki.fi>
date: Mon Jan 27 16:35:46 2014 +0200
description:
acl plugin: Added an alternative global ACL file that can contain mailbox patterns.
Instead of pointing the global ACL path to a directory use a file instead.
The file format is "<mailbox pattern> <normal ACL line>". Most importantly
this can be used to specify default ACLs for namespaces.
The mailbox pattern uses "*" and "?" wildcards currently. I'm not sure if I
should still change them to IMAP "*" and "%" wildcards. That would make the
behavior more complex ("%" depends on hierarchy separator), slightly slower
and quota code is already also using the */? wildcards..
diffstat:
src/plugins/acl/Makefile.am | 2 +
src/plugins/acl/acl-api-private.h | 6 +-
src/plugins/acl/acl-api.c | 28 +++++
src/plugins/acl/acl-api.h | 1 +
src/plugins/acl/acl-backend-vfile.c | 114 +++++++++++++++------
src/plugins/acl/acl-backend-vfile.h | 4 +-
src/plugins/acl/acl-global-file.c | 191 ++++++++++++++++++++++++++++++++++++
src/plugins/acl/acl-global-file.h | 20 +++
8 files changed, 330 insertions(+), 36 deletions(-)
diffs (truncated from 572 to 300 lines):
diff -r 1a54118f4690 -r 9376bf098692 src/plugins/acl/Makefile.am
--- a/src/plugins/acl/Makefile.am Mon Jan 27 14:25:03 2014 +0200
+++ b/src/plugins/acl/Makefile.am Mon Jan 27 16:35:46 2014 +0200
@@ -24,6 +24,7 @@
acl-backend-vfile-acllist.c \
acl-backend-vfile-update.c \
acl-cache.c \
+ acl-global-file.c \
acl-lookup-dict.c \
acl-mailbox.c \
acl-mailbox-list.c \
@@ -36,6 +37,7 @@
acl-api-private.h \
acl-backend-vfile.h \
acl-cache.h \
+ acl-global-file.h \
acl-lookup-dict.h \
acl-plugin.h \
acl-shared-storage.h \
diff -r 1a54118f4690 -r 9376bf098692 src/plugins/acl/acl-api-private.h
--- a/src/plugins/acl/acl-api-private.h Mon Jan 27 14:25:03 2014 +0200
+++ b/src/plugins/acl/acl-api-private.h Mon Jan 27 16:35:46 2014 +0200
@@ -49,6 +49,7 @@
struct mailbox_list *list;
struct acl_cache *cache;
+ struct acl_global_file *global_file;
struct acl_object *default_aclobj;
struct acl_mask *default_aclmask;
@@ -69,7 +70,7 @@
char *name;
pool_t rights_pool;
- ARRAY(struct acl_rights) rights;
+ ARRAY_TYPE(acl_rights) rights;
};
struct acl_object_list_iter {
@@ -103,6 +104,8 @@
const char *acl_rights_export(const struct acl_rights *rights);
int acl_rights_parse_line(const char *line, pool_t pool,
struct acl_rights *rights_r, const char **error_r);
+void acl_rights_dup(const struct acl_rights *src,
+ pool_t pool, struct acl_rights *dest_r);
int acl_rights_cmp(const struct acl_rights *r1, const struct acl_rights *r2);
void acl_rights_sort(struct acl_object *aclobj);
@@ -117,5 +120,6 @@
enum acl_modify_mode modify_mode);
void acl_object_rebuild_cache(struct acl_object *aclobj);
void acl_object_remove_all_access(struct acl_object *aclobj);
+void acl_object_add_global_acls(struct acl_object *aclobj);
#endif
diff -r 1a54118f4690 -r 9376bf098692 src/plugins/acl/acl-api.c
--- a/src/plugins/acl/acl-api.c Mon Jan 27 14:25:03 2014 +0200
+++ b/src/plugins/acl/acl-api.c Mon Jan 27 16:35:46 2014 +0200
@@ -7,6 +7,7 @@
#include "hash.h"
#include "mail-user.h"
#include "mailbox-list.h"
+#include "acl-global-file.h"
#include "acl-cache.h"
#include "acl-api-private.h"
@@ -420,6 +421,19 @@
return 0;
}
+void acl_rights_dup(const struct acl_rights *src,
+ pool_t pool, struct acl_rights *dest_r)
+{
+ memset(dest_r, 0, sizeof(*dest_r));
+ dest_r->id_type = src->id_type;
+ dest_r->identifier = p_strdup(pool, src->identifier);
+ dest_r->rights = src->rights == NULL ? NULL :
+ p_strarray_dup(pool, src->rights);
+ dest_r->neg_rights = src->neg_rights == NULL ? NULL :
+ p_strarray_dup(pool, src->neg_rights);
+ dest_r->global = src->global;
+}
+
int acl_rights_cmp(const struct acl_rights *r1, const struct acl_rights *r2)
{
int ret;
@@ -803,3 +817,17 @@
rights.rights = &null;
array_append(&aclobj->rights, &rights, 1);
}
+
+void acl_object_add_global_acls(struct acl_object *aclobj)
+{
+ struct acl_backend *backend = aclobj->backend;
+ const char *vname, *error;
+
+ if (mailbox_list_is_valid_name(backend->list, aclobj->name, &error))
+ vname = mailbox_list_get_vname(backend->list, aclobj->name);
+ else
+ vname = "";
+
+ acl_global_file_get(backend->global_file, vname,
+ aclobj->rights_pool, &aclobj->rights);
+}
diff -r 1a54118f4690 -r 9376bf098692 src/plugins/acl/acl-api.h
--- a/src/plugins/acl/acl-api.h Mon Jan 27 14:25:03 2014 +0200
+++ b/src/plugins/acl/acl-api.h Mon Jan 27 16:35:46 2014 +0200
@@ -79,6 +79,7 @@
/* These rights are global for all users */
unsigned int global:1;
};
+ARRAY_DEFINE_TYPE(acl_rights, struct acl_rights);
struct acl_rights_update {
struct acl_rights rights;
diff -r 1a54118f4690 -r 9376bf098692 src/plugins/acl/acl-backend-vfile.c
--- a/src/plugins/acl/acl-backend-vfile.c Mon Jan 27 14:25:03 2014 +0200
+++ b/src/plugins/acl/acl-backend-vfile.c Mon Jan 27 16:35:46 2014 +0200
@@ -6,6 +6,7 @@
#include "istream.h"
#include "nfs-workarounds.h"
#include "mail-storage-private.h"
+#include "acl-global-file.h"
#include "acl-cache.h"
#include "acl-backend-vfile.h"
@@ -32,10 +33,11 @@
{
struct acl_backend_vfile *backend =
(struct acl_backend_vfile *)_backend;
+ struct stat st;
const char *const *tmp;
tmp = t_strsplit(data, ":");
- backend->global_dir = p_strdup_empty(_backend->pool, *tmp);
+ backend->global_path = p_strdup_empty(_backend->pool, *tmp);
backend->cache_secs = ACL_VFILE_DEFAULT_CACHE_SECS;
if (*tmp != NULL)
@@ -52,10 +54,28 @@
return -1;
}
}
+ if (backend->global_path != NULL) {
+ if (stat(backend->global_path, &st) < 0) {
+ if (errno != ENOENT) {
+ i_error("acl vfile: stat(%s) failed: %m",
+ backend->global_path);
+ return -1;
+ }
+ } else if (!S_ISDIR(st.st_mode)) {
+ _backend->global_file =
+ acl_global_file_init(backend->global_path, backend->cache_secs);
+ }
+ }
if (_backend->debug) {
- i_debug("acl vfile: Global ACL directory: %s",
- backend->global_dir == NULL ? "(none)" :
- backend->global_dir);
+ if (backend->global_path == NULL)
+ i_debug("acl vfile: Global ACLs disabled");
+ else if (_backend->global_file != NULL) {
+ i_debug("acl vfile: Global ACL file: %s",
+ backend->global_path);
+ } else {
+ i_debug("acl vfile: Global ACL legacy directory: %s",
+ backend->global_path);
+ }
}
_backend->cache =
@@ -73,28 +93,27 @@
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);
}
static const char *
acl_backend_vfile_get_local_dir(struct acl_backend *backend,
- const char *name)
+ const char *name, const char *vname)
{
struct mail_namespace *ns = mailbox_list_get_namespace(backend->list);
struct mailbox_list *list = ns->list;
struct mail_storage *storage;
enum mailbox_list_path_type type;
- const char *dir, *inbox, *vname, *error;
+ const char *dir, *inbox;
if (*name == '\0')
name = NULL;
- else if (!mailbox_list_is_valid_name(list, name, &error))
- return NULL;
/* ACL files are very important. try to keep them among the main
mail files. that's not possible though with a) if the mailbox is
a file or b) if the mailbox path doesn't point to filesystem. */
- vname = name == NULL ? "" : mailbox_list_get_vname(backend->list, name);
if (mailbox_list_get_storage(&list, vname, &storage) < 0)
return NULL;
i_assert(list == ns->list);
@@ -104,7 +123,7 @@
MAILBOX_LIST_PATH_TYPE_CONTROL : MAILBOX_LIST_PATH_TYPE_MAILBOX;
if (name == NULL) {
if (!mailbox_list_get_root_path(list, type, &dir))
- return FALSE;
+ return NULL;
} else {
if (mailbox_list_get_path(list, name, type, &dir) <= 0)
return NULL;
@@ -129,22 +148,30 @@
struct acl_backend_vfile *backend =
(struct acl_backend_vfile *)_backend;
struct acl_object_vfile *aclobj;
- const char *dir, *vname;
+ const char *dir, *vname, *error;
aclobj = i_new(struct acl_object_vfile, 1);
aclobj->aclobj.backend = _backend;
aclobj->aclobj.name = i_strdup(name);
T_BEGIN {
- if (backend->global_dir != NULL) {
- vname = mailbox_list_get_vname(backend->backend.list, name);
- aclobj->global_path =
- i_strconcat(backend->global_dir, "/", vname, NULL);
+ if (*name == '\0' ||
+ mailbox_list_is_valid_name(_backend->list, name, &error)) {
+ vname = *name == '\0' ? "" :
+ mailbox_list_get_vname(_backend->list, name);
+
+ dir = acl_backend_vfile_get_local_dir(_backend, name, vname);
+ aclobj->local_path = dir == NULL ? NULL :
+ i_strconcat(dir, "/"ACL_FILENAME, NULL);
+ if (backend->global_path != NULL &&
+ _backend->global_file == NULL) {
+ aclobj->global_path =
+ i_strconcat(backend->global_path, "/", name, NULL);
+ }
+ } else {
+ /* Invalid mailbox name, just use the default
+ global ACL files */
}
-
- dir = acl_backend_vfile_get_local_dir(_backend, name);
- aclobj->local_path = dir == NULL ? NULL :
- i_strconcat(dir, "/"ACL_FILENAME, NULL);
} T_END;
return &aclobj->aclobj;
}
@@ -193,7 +220,8 @@
struct acl_backend_vfile *backend =
(struct acl_backend_vfile *)_backend;
struct acl_backend_vfile_validity *old_validity, new_validity;
- const char *path, *local_path, *global_path, *dir;
+ const char *path, *local_path, *global_path, *dir, *vname = "";
+ const char *error;
int ret;
old_validity = acl_cache_get_validity(_backend->cache, name);
@@ -212,16 +240,28 @@
ret = acl_backend_vfile_exists(backend, path,
&new_validity.mailbox_validity);
}
+
if (ret == 0 &&
- (dir = acl_backend_vfile_get_local_dir(_backend, name)) != NULL) {
- local_path = t_strconcat(dir, "/", name, NULL);
- ret = acl_backend_vfile_exists(backend, local_path,
- &new_validity.local_validity);
+ (*name == '\0' ||
+ mailbox_list_is_valid_name(_backend->list, name, &error))) {
+ vname = *name == '\0' ? "" :
+ mailbox_list_get_vname(_backend->list, name);
+ dir = acl_backend_vfile_get_local_dir(_backend, name, vname);
+ if (dir != NULL) {
+ local_path = t_strconcat(dir, "/", name, NULL);
+ ret = acl_backend_vfile_exists(backend, local_path,
+ &new_validity.local_validity);
+ }
}
- if (ret == 0 && backend->global_dir != NULL) {
- global_path = t_strconcat(backend->global_dir, "/", name, NULL);
- ret = acl_backend_vfile_exists(backend, global_path,
- &new_validity.global_validity);
+
+ if (ret == 0 && backend->global_path != NULL) {
+ if (_backend->global_file != NULL)
+ ret = acl_global_file_have_any(_backend->global_file, vname) ? 1 : 0;
+ else {
+ global_path = t_strconcat(backend->global_path, "/", name, NULL);
+ ret = acl_backend_vfile_exists(backend, global_path,
+ &new_validity.global_validity);
+ }
}
acl_cache_set_validity(_backend->cache, name, &new_validity);
return ret > 0;
More information about the dovecot-cvs
mailing list