]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap-acl: GETACL: Convert "owner" to the actual username whenever possible.
authorTimo Sirainen <tss@iki.fi>
Fri, 20 Feb 2009 21:26:41 +0000 (16:26 -0500)
committerTimo Sirainen <tss@iki.fi>
Fri, 20 Feb 2009 21:26:41 +0000 (16:26 -0500)
--HG--
branch : HEAD

src/plugins/acl/acl-api-private.h
src/plugins/acl/acl-api.c
src/plugins/acl/acl-api.h
src/plugins/acl/acl-backend-vfile.c
src/plugins/acl/acl-backend.c
src/plugins/imap-acl/imap-acl-plugin.c

index 7b31392175cc3188636d458db06d7ff891da2a0b..83c72157ca4746c6a346aca2874b2d88708d08a0 100644 (file)
@@ -73,7 +73,6 @@ struct acl_object_list_iter {
        struct acl_object *aclobj;
 
        unsigned int idx;
-       unsigned int returned_owner:1;
        unsigned int failed:1;
 };
 
index ac750dda556459cae74e66923d4f662b97ccf90c..47c6a31187eb1a75a60ab5d1cb913f1b2e85536c 100644 (file)
@@ -124,6 +124,13 @@ int acl_object_get_my_rights(struct acl_object *aclobj, pool_t pool,
        return ret;
 }
 
+const char *const *acl_object_get_default_rights(struct acl_object *aclobj)
+{
+       return acl_backend_mask_get_names(aclobj->backend,
+                                         aclobj->backend->default_aclmask,
+                                         pool_datastack_create());
+}
+
 int acl_object_update(struct acl_object *aclobj,
                      const struct acl_rights_update *update)
 {
index 785420684fdd4913cf6491715e15d922f6750ad0..56de5b8ad63522f4d5e5dfff81a33924a85af59c 100644 (file)
@@ -92,6 +92,11 @@ acl_backend_init(const char *data, struct mailbox_list *list,
                 const char *acl_username, const char *const *groups,
                 bool owner);
 void acl_backend_deinit(struct acl_backend **backend);
+
+/* Returns the acl_username passed to acl_backend_init(). Note that with
+   anonymous users NULL is returned. */
+const char *acl_backend_get_acl_username(struct acl_backend *backend);
+
 /* Returns TRUE if user isn't anonymous. */
 bool acl_backend_user_is_authenticated(struct acl_backend *backend);
 /* Returns TRUE if user owns the storage. */
@@ -128,6 +133,8 @@ int acl_object_have_right(struct acl_object *aclobj, unsigned int right_idx);
 /* Returns 0 = ok, -1 = internal error */
 int acl_object_get_my_rights(struct acl_object *aclobj, pool_t pool,
                             const char *const **rights_r);
+/* Returns the default rights for the object. */
+const char *const *acl_object_get_default_rights(struct acl_object *aclobj);
 
 /* Update ACL of given object. */
 int acl_object_update(struct acl_object *aclobj,
index cc570a17a9976d9b3e35502a5f828ca8a678e020..82990058d65b72796620a9b1746b79ccf8bc25f6 100644 (file)
@@ -1127,7 +1127,6 @@ acl_backend_vfile_object_list_init(struct acl_object *_aclobj)
        struct acl_object_vfile *aclobj =
                (struct acl_object_vfile *)_aclobj;
        struct acl_object_list_iter *iter;
-       struct mail_namespace *ns;
 
        iter = i_new(struct acl_object_list_iter, 1);
        iter->aclobj = _aclobj;
@@ -1138,12 +1137,6 @@ acl_backend_vfile_object_list_init(struct acl_object *_aclobj)
                acl_cache_flush(_aclobj->backend->cache, _aclobj->name);
        }
 
-       /* be sure to return owner for private namespaces.
-          (other namespaces don't have an owner) */
-       ns = mailbox_list_get_namespace(_aclobj->backend->list);
-       if (ns->type != NAMESPACE_PRIVATE)
-               iter->returned_owner = TRUE;
-
        if (_aclobj->backend->v.object_refresh_cache(_aclobj) < 0)
                iter->failed = TRUE;
        return iter;
@@ -1157,26 +1150,10 @@ acl_backend_vfile_object_list_next(struct acl_object_list_iter *iter,
                (struct acl_object_vfile *)iter->aclobj;
        const struct acl_rights *rights;
 
-       if (iter->idx == array_count(&aclobj->rights)) {
-               struct acl_backend *backend = iter->aclobj->backend;
-
-               if (iter->returned_owner)
-                       return 0;
-
-               /* return missing owner based on the default ACLs */
-               iter->returned_owner = TRUE;
-               memset(rights_r, 0, sizeof(*rights_r));
-               rights_r->id_type = ACL_ID_OWNER;
-               rights_r->rights =
-                       acl_backend_mask_get_names(backend,
-                                                  backend->default_aclmask,
-                                                  pool_datastack_create());
-               return 1;
-       }
+       if (iter->idx == array_count(&aclobj->rights))
+               return 0;
 
        rights = array_idx(&aclobj->rights, iter->idx++);
-       if (rights->id_type == ACL_ID_OWNER && rights->rights != NULL)
-               iter->returned_owner = TRUE;
        *rights_r = *rights;
        return 1;
 }
index dbd12c021587dc7269f87af6afff1250d74c1452..741b6ccd11df4820fe4455be22c55253d1646c07 100644 (file)
@@ -95,6 +95,11 @@ void acl_backend_deinit(struct acl_backend **_backend)
        backend->v.deinit(backend);
 }
 
+const char *acl_backend_get_acl_username(struct acl_backend *backend)
+{
+       return backend->username;
+}
+
 bool acl_backend_user_is_authenticated(struct acl_backend *backend)
 {
        return backend->username != NULL;
index 5a2f5b1c86b1397530faa76f44bb62b9d1ffb7b7..ff352e1665f049564fcf280d8d470e224af75aae 100644 (file)
@@ -162,16 +162,51 @@ imap_acl_write_right(string_t *dest, string_t *tmp,
        imap_acl_write_rights_list(dest, rights);
 }
 
-static int imap_acl_write_aclobj(string_t *dest, struct acl_object *aclobj)
+static int
+imap_acl_write_aclobj(string_t *dest, struct acl_backend *backend,
+                     struct acl_object *aclobj, bool convert_owner)
 {
        struct acl_object_list_iter *iter;
        struct acl_rights rights;
        string_t *tmp;
+       const char *username;
+       unsigned int orig_len = str_len(dest);
+       bool owner, seen_owner = FALSE, seen_positive_owner = FALSE;
        int ret;
 
+       username = acl_backend_get_acl_username(backend);
+       if (username == NULL)
+               convert_owner = FALSE;
+
        tmp = t_str_new(128);
        iter = acl_object_list_init(aclobj);
        while ((ret = acl_object_list_next(iter, &rights)) > 0) {
+               if (rights.id_type == ACL_ID_USER &&
+                   acl_backend_user_name_equals(backend, rights.identifier))
+                       owner = TRUE;
+               else if (rights.id_type == ACL_ID_OWNER) {
+                       owner = TRUE;
+                       if (convert_owner) {
+                               rights.id_type = ACL_ID_USER;
+                               rights.identifier = username;
+                       }
+               } else {
+                       owner = FALSE;
+               }
+
+               if (owner) {
+                       if (seen_owner && convert_owner) {
+                               /* oops, we have both owner and user=myself.
+                                  can't do the conversion, so try again. */
+                               str_truncate(dest, orig_len);
+                               return imap_acl_write_aclobj(dest, backend,
+                                                            aclobj, FALSE);
+                       }
+                       seen_owner = TRUE;
+                       if (rights.rights != NULL)
+                               seen_positive_owner = TRUE;
+               }
+
                if (rights.rights != NULL) {
                        str_append_c(dest, ' ');
                        imap_acl_write_right(dest, tmp, &rights, FALSE);
@@ -182,11 +217,28 @@ static int imap_acl_write_aclobj(string_t *dest, struct acl_object *aclobj)
                }
        }
        acl_object_list_deinit(&iter);
+
+       if (!seen_positive_owner && username != NULL) {
+               /* no positive owner rights returned, write default ACLs */
+               memset(&rights, 0, sizeof(rights));
+               if (!convert_owner) {
+                       rights.id_type = ACL_ID_OWNER;
+               } else {
+                       rights.id_type = ACL_ID_USER;
+                       rights.identifier = username;
+               }
+               rights.rights = acl_object_get_default_rights(aclobj);
+               if (rights.rights != NULL) {
+                       str_append_c(dest, ' ');
+                       imap_acl_write_right(dest, tmp, &rights, FALSE);
+               }
+       }
        return ret;
 }
 
 static bool cmd_getacl(struct client_command_context *cmd)
 {
+       struct acl_backend *backend;
        struct mailbox *box;
        const char *mailbox;
        string_t *str;
@@ -207,7 +259,9 @@ static bool cmd_getacl(struct client_command_context *cmd)
        imap_quote_append_string(str, mailbox, FALSE);
        len = str_len(str);
 
-       ret = imap_acl_write_aclobj(str, acl_mailbox_get_aclobj(box));
+       backend = acl_storage_get_backend(mailbox_get_storage(box));
+       ret = imap_acl_write_aclobj(str, backend,
+                                   acl_mailbox_get_aclobj(box), TRUE);
        if (ret == 0) {
                client_send_line(cmd->client, str_c(str));
                client_send_tagline(cmd, "OK Getacl completed.");