dovecot-1.2: Added IMAP ACL commands with ability to modify ACLs.

dovecot at dovecot.org dovecot at dovecot.org
Sun Nov 16 04:46:19 EET 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/29b1ec15880a
changeset: 8418:29b1ec15880a
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Nov 16 04:46:14 2008 +0200
description:
Added IMAP ACL commands with ability to modify ACLs.
Based on patch by Bernhard Herzog and Sascha Wilde.

diffstat:

14 files changed, 951 insertions(+), 92 deletions(-)
configure.in                           |    1 
src/plugins/Makefile.am                |    1 
src/plugins/acl/Makefile.am            |    3 
src/plugins/acl/acl-api-private.h      |   13 
src/plugins/acl/acl-api.c              |   54 ++-
src/plugins/acl/acl-api.h              |   13 
src/plugins/acl/acl-backend-vfile.c    |  384 ++++++++++++++++++++++++---
src/plugins/acl/acl-cache.c            |    2 
src/plugins/acl/acl-mailbox.c          |   46 ++-
src/plugins/acl/acl-plugin.h           |   16 -
src/plugins/acl/acl-storage.h          |   28 +
src/plugins/imap-acl/Makefile.am       |   20 +
src/plugins/imap-acl/imap-acl-plugin.c |  455 ++++++++++++++++++++++++++++++++
src/plugins/imap-acl/imap-acl-plugin.h |    7 

diffs (truncated from 1400 to 300 lines):

diff -r 106ad33091ca -r 29b1ec15880a configure.in
--- a/configure.in	Sun Nov 16 04:45:06 2008 +0200
+++ b/configure.in	Sun Nov 16 04:46:14 2008 +0200
@@ -2453,6 +2453,7 @@ src/util/Makefile
 src/util/Makefile
 src/plugins/Makefile
 src/plugins/acl/Makefile
+src/plugins/imap-acl/Makefile
 src/plugins/autocreate/Makefile
 src/plugins/convert/Makefile
 src/plugins/expire/Makefile
diff -r 106ad33091ca -r 29b1ec15880a src/plugins/Makefile.am
--- a/src/plugins/Makefile.am	Sun Nov 16 04:45:06 2008 +0200
+++ b/src/plugins/Makefile.am	Sun Nov 16 04:46:14 2008 +0200
@@ -12,6 +12,7 @@ endif
 
 SUBDIRS = \
 	acl \
+	imap-acl \
 	autocreate \
 	convert \
 	expire \
diff -r 106ad33091ca -r 29b1ec15880a src/plugins/acl/Makefile.am
--- a/src/plugins/acl/Makefile.am	Sun Nov 16 04:45:06 2008 +0200
+++ b/src/plugins/acl/Makefile.am	Sun Nov 16 04:46:14 2008 +0200
@@ -26,7 +26,8 @@ noinst_HEADERS = \
 	acl-api-private.h \
 	acl-backend-vfile.h \
 	acl-cache.h \
-	acl-plugin.h
+	acl-plugin.h \
+	acl-storage.h
 
 install-exec-local:
 	for d in imap lda; do \
diff -r 106ad33091ca -r 29b1ec15880a src/plugins/acl/acl-api-private.h
--- a/src/plugins/acl/acl-api-private.h	Sun Nov 16 04:45:06 2008 +0200
+++ b/src/plugins/acl/acl-api-private.h	Sun Nov 16 04:46:14 2008 +0200
@@ -2,6 +2,13 @@
 #define ACL_API_PRIVATE_H
 
 #include "acl-api.h"
+
+#define ACL_ID_NAME_ANYONE "anyone"
+#define ACL_ID_NAME_AUTHENTICATED "authenticated"
+#define ACL_ID_NAME_OWNER "owner"
+#define ACL_ID_NAME_USER_PREFIX "user="
+#define ACL_ID_NAME_GROUP_PREFIX "group="
+#define ACL_ID_NAME_GROUP_OVERRIDE_PREFIX "group-override="
 
 struct acl_backend_vfuncs {
 	struct acl_backend *(*alloc)(void);
@@ -25,7 +32,7 @@ struct acl_backend_vfuncs {
 
 	int (*object_refresh_cache)(struct acl_object *aclobj);
 	int (*object_update)(struct acl_object *aclobj,
-			     const struct acl_rights_update *rights);
+			     const struct acl_rights_update *update);
 
 	struct acl_object_list_iter *
 		(*object_list_init)(struct acl_object *aclobj);
@@ -65,9 +72,13 @@ struct acl_object_list_iter {
 	struct acl_object *aclobj;
 
 	unsigned int idx;
+	unsigned int returned_owner:1;
 	unsigned int failed:1;
 };
 
+const char *const *
+acl_backend_mask_get_names(struct acl_backend *backend,
+			   const struct acl_mask *mask, pool_t pool);
 int acl_backend_get_default_rights(struct acl_backend *backend,
 				   const struct acl_mask **mask_r);
 
diff -r 106ad33091ca -r 29b1ec15880a src/plugins/acl/acl-api.c
--- a/src/plugins/acl/acl-api.c	Sun Nov 16 04:45:06 2008 +0200
+++ b/src/plugins/acl/acl-api.c	Sun Nov 16 04:46:14 2008 +0200
@@ -52,30 +52,13 @@ int acl_object_have_right(struct acl_obj
 	return acl_cache_mask_isset(have_mask, right_idx);
 }
 
-static int acl_object_get_my_rights_real(struct acl_object *aclobj, pool_t pool,
-					 const char *const **rights_r)
+const char *const *
+acl_backend_mask_get_names(struct acl_backend *backend,
+			   const struct acl_mask *mask, pool_t pool)
 {
-	struct acl_backend *backend = aclobj->backend;
-	const struct acl_mask *mask;
 	const char *const *names;
 	const char **buf, **rights;
 	unsigned int names_count, count, i, j, name_idx;
-
-	if (*aclobj->name == '\0') {
-		/* we want to look up default rights */
-		if (acl_backend_get_default_rights(backend, &mask) < 0)
-			return -1;
-	} else {
-		if (backend->v.object_refresh_cache(aclobj) < 0)
-			return -1;
-
-		mask = acl_cache_get_my_rights(backend->cache,
-					       aclobj->name);
-		if (mask == NULL) {
-			if (acl_backend_get_default_rights(backend, &mask) < 0)
-				return -1;
-		}
-	}
 
 	names = acl_cache_get_names(backend->cache, &names_count);
 	buf = t_new(const char *, (mask->size * CHAR_BIT) + 1);
@@ -98,7 +81,32 @@ static int acl_object_get_my_rights_real
 	/* @UNSAFE */
 	rights = p_new(pool, const char *, count + 1);
 	memcpy(rights, buf, count * sizeof(const char *));
-	*rights_r = rights;
+	return rights;
+}
+
+static int acl_object_get_my_rights_real(struct acl_object *aclobj, pool_t pool,
+					 const char *const **rights_r)
+{
+	struct acl_backend *backend = aclobj->backend;
+	const struct acl_mask *mask;
+
+	if (*aclobj->name == '\0') {
+		/* we want to look up default rights */
+		if (acl_backend_get_default_rights(backend, &mask) < 0)
+			return -1;
+	} else {
+		if (backend->v.object_refresh_cache(aclobj) < 0)
+			return -1;
+
+		mask = acl_cache_get_my_rights(backend->cache,
+					       aclobj->name);
+		if (mask == NULL) {
+			if (acl_backend_get_default_rights(backend, &mask) < 0)
+				return -1;
+		}
+	}
+
+	*rights_r = acl_backend_mask_get_names(backend, mask, pool);
 	return 0;
 }
 
@@ -116,9 +124,9 @@ int acl_object_get_my_rights(struct acl_
 }
 
 int acl_object_update(struct acl_object *aclobj,
-		      const struct acl_rights_update *rights)
+		      const struct acl_rights_update *update)
 {
-        return aclobj->backend->v.object_update(aclobj, rights);
+        return aclobj->backend->v.object_update(aclobj, update);
 }
 
 struct acl_object_list_iter *acl_object_list_init(struct acl_object *aclobj)
diff -r 106ad33091ca -r 29b1ec15880a src/plugins/acl/acl-api.h
--- a/src/plugins/acl/acl-api.h	Sun Nov 16 04:45:06 2008 +0200
+++ b/src/plugins/acl/acl-api.h	Sun Nov 16 04:46:14 2008 +0200
@@ -3,6 +3,7 @@
 
 struct mailbox_list;
 struct mail_storage;
+struct mailbox;
 struct acl_object;
 
 /* Show mailbox in mailbox list. Allow subscribing to it. */
@@ -48,12 +49,14 @@ enum acl_id_type {
 };
 
 enum acl_modify_mode {
+	/* Remove rights from existing ACL */
+	ACL_MODIFY_MODE_REMOVE = 0,
 	/* Add rights to existing ACL (or create a new one) */
-	ACL_MODIFY_MODE_ADD = 0,
-	/* Remove rights from existing ACL */
-	ACL_MODIFY_MODE_REMOVE,
+	ACL_MODIFY_MODE_ADD,
 	/* Replace existing ACL with given rights */
-	ACL_MODIFY_MODE_REPLACE
+	ACL_MODIFY_MODE_REPLACE,
+	/* Clear all the rights from an existing ACL */
+	ACL_MODIFY_MODE_CLEAR
 };
 
 struct acl_rights {
@@ -126,7 +129,7 @@ int acl_object_get_my_rights(struct acl_
 
 /* Update ACL of given object. */
 int acl_object_update(struct acl_object *aclobj,
-		      const struct acl_rights_update *rights);
+		      const struct acl_rights_update *update);
 
 /* List all identifiers. */
 struct acl_object_list_iter *acl_object_list_init(struct acl_object *aclobj);
diff -r 106ad33091ca -r 29b1ec15880a src/plugins/acl/acl-backend-vfile.c
--- a/src/plugins/acl/acl-backend-vfile.c	Sun Nov 16 04:45:06 2008 +0200
+++ b/src/plugins/acl/acl-backend-vfile.c	Sun Nov 16 04:46:14 2008 +0200
@@ -3,9 +3,14 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "array.h"
+#include "bsearch-insert-pos.h"
+#include "str.h"
 #include "istream.h"
+#include "ostream.h"
+#include "file-dotlock.h"
 #include "nfs-workarounds.h"
 #include "mail-storage-private.h"
+#include "mail-namespace.h"
 #include "acl-cache.h"
 #include "acl-backend-vfile.h"
 
@@ -52,6 +57,14 @@ static const struct acl_letter_map acl_l
 	{ '\0', NULL }
 };
 
+static struct dotlock_settings dotlock_set = {
+	MEMBER(temp_prefix) NULL,
+	MEMBER(lock_suffix) NULL,
+
+	MEMBER(timeout) 30,
+	MEMBER(stale_timeout) 120
+};
+
 static struct acl_backend *acl_backend_vfile_alloc(void)
 {
 	struct acl_backend_vfile *backend;
@@ -266,7 +279,8 @@ static void acl_backend_vfile_object_dei
 }
 
 static const char *const *
-acl_rights_alloc(pool_t pool, ARRAY_TYPE(const_string) *rights_arr)
+acl_rights_alloc(pool_t pool, ARRAY_TYPE(const_string) *rights_arr,
+		 bool dup_strings)
 {
 	const char **ret, **rights;
 	unsigned int i, dest, count;
@@ -283,6 +297,11 @@ acl_rights_alloc(pool_t pool, ARRAY_TYPE
 			if (strcmp(rights[i-1], rights[i]) != 0)
 				ret[dest++] = rights[i];
 		}
+		ret[dest] = NULL;
+		if (dup_strings) {
+			for (i = 0; i < dest; i++)
+				ret[i] = p_strdup(pool, ret[i]);
+		}
 	}
 	return ret;
 }
@@ -326,7 +345,7 @@ acl_parse_rights(pool_t pool, const char
 		}
 	}
 
-	return acl_rights_alloc(pool, &rights);
+	return acl_rights_alloc(pool, &rights, FALSE);
 }
 
 static int
@@ -362,31 +381,34 @@ acl_object_vfile_parse_line(struct acl_o
 
 	switch (*line) {
 	case 'u':
-		if (strncmp(line, "user=", 5) == 0) {
+		if (strncmp(line, ACL_ID_NAME_USER_PREFIX,
+			    strlen(ACL_ID_NAME_USER_PREFIX)) == 0) {
 			rights.id_type = ACL_ID_USER;
 			rights.identifier = line + 5;
 			break;
 		}
 	case 'o':
-		if (strcmp(line, "owner") == 0) {
+		if (strcmp(line, ACL_ID_NAME_OWNER) == 0) {
 			rights.id_type = ACL_ID_OWNER;
 			break;
 		}
 	case 'g':
-		if (strncmp(line, "group=", 6) == 0) {
+		if (strncmp(line, ACL_ID_NAME_GROUP_PREFIX,
+			    strlen(ACL_ID_NAME_GROUP_PREFIX)) == 0) {
 			rights.id_type = ACL_ID_GROUP;
 			rights.identifier = line + 6;
 			break;
-		} else if (strncmp(line, "group-override=", 15) == 0) {
+		} else if (strncmp(line, ACL_ID_NAME_GROUP_OVERRIDE_PREFIX,
+				   strlen(ACL_ID_NAME_GROUP_OVERRIDE_PREFIX)) == 0) {
 			rights.id_type = ACL_ID_GROUP_OVERRIDE;
 			rights.identifier = line + 15;
 			break;
 		}
 	case 'a':
-		if (strcmp(line, "authenticated") == 0) {
+		if (strcmp(line, ACL_ID_NAME_AUTHENTICATED) == 0) {
 			rights.id_type = ACL_ID_AUTHENTICATED;
 			break;
-		} else if (strcmp(line, "anyone") == 0 ||
+		} else if (strcmp(line, ACL_ID_NAME_ANYONE) == 0 ||
 			   strcmp(line, "anonymous") == 0) {


More information about the dovecot-cvs mailing list