struct acl_object *aclobj;
unsigned int idx;
- unsigned int returned_owner:1;
unsigned int failed:1;
};
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)
{
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. */
/* 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,
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;
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;
(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;
}
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;
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);
}
}
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;
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.");