dovecot-2.2: Various cleanups to checking if mailbox name is valid.
dovecot at dovecot.org
dovecot at dovecot.org
Tue Sep 25 22:53:59 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/20edc46254ce
changeset: 15107:20edc46254ce
user: Timo Sirainen <tss at iki.fi>
date: Tue Sep 25 22:53:36 2012 +0300
description:
Various cleanups to checking if mailbox name is valid.
diffstat:
src/doveadm/dsync/dsync-brain-mailbox-tree.c | 116 +++++++++++----------
src/lib-storage/list/mailbox-list-fs-iter.c | 6 +-
src/lib-storage/list/mailbox-list-fs.c | 4 +-
src/lib-storage/list/mailbox-list-subscriptions.c | 8 +-
src/lib-storage/mail-storage.c | 51 +++++++--
src/lib-storage/mail-storage.h | 3 +
src/lib-storage/mailbox-list.c | 76 ++++++--------
src/lib-storage/mailbox-list.h | 12 +-
src/plugins/acl/acl-backend-vfile.c | 4 +-
9 files changed, 151 insertions(+), 129 deletions(-)
diffs (truncated from 515 to 300 lines):
diff -r f0d487918a2b -r 20edc46254ce src/doveadm/dsync/dsync-brain-mailbox-tree.c
--- a/src/doveadm/dsync/dsync-brain-mailbox-tree.c Tue Sep 25 22:51:46 2012 +0300
+++ b/src/doveadm/dsync/dsync-brain-mailbox-tree.c Tue Sep 25 22:53:36 2012 +0300
@@ -173,66 +173,71 @@
return best_ns;
}
-static const char *
-mailbox_name_cleanup(const char *input, char real_sep, char alt_char)
+static bool
+dsync_is_valid_name(struct mail_namespace *ns, const char *vname)
{
- char *output, *p;
+ struct mailbox *box;
+ bool ret;
- output = t_strdup_noconst(input);
- for (p = output; *p != '\0'; p++) {
- if (*p == real_sep || (uint8_t)*input < 32 ||
- (uint8_t)*input >= 0x80)
+ box = mailbox_alloc(ns->list, vname, 0);
+ ret = mailbox_verify_create_name(box) == 0;
+ mailbox_free(&box);
+ return ret;
+}
+
+static void
+dsync_fix_mailbox_name(struct mail_namespace *ns, string_t *vname,
+ char alt_char)
+{
+ const char *old_vname;
+ char *p, list_sep = mailbox_list_get_hierarchy_sep(ns->list);
+ guid_128_t guid;
+
+ /* replace control chars */
+ for (p = str_c_modifiable(vname); *p != '\0'; p++) {
+ if ((unsigned char)*p < ' ')
*p = alt_char;
}
- return output;
-}
+ /* make it valid UTF8 */
+ if (!uni_utf8_str_is_valid(str_c(vname))) {
+ old_vname = t_strdup(str_c(vname));
+ str_truncate(vname, 0);
+ if (uni_utf8_get_valid_data((const void *)old_vname,
+ strlen(old_vname), vname))
+ i_unreached();
+ }
+ if (dsync_is_valid_name(ns, str_c(vname)))
+ return;
-static const char *mailbox_name_force_cleanup(const char *input, char alt_char)
-{
- char *output, *p;
+ /* 1) change any real separators to alt separators (this wouldn't
+ be necessary with listescape, but don't bother detecting it) */
+ if (list_sep != mail_namespace_get_sep(ns)) {
+ for (p = str_c_modifiable(vname); *p != '\0'; p++) {
+ if (*p == list_sep)
+ *p = alt_char;
+ }
+ if (dsync_is_valid_name(ns, str_c(vname)))
+ return;
+ }
+ /* 2) '/' characters aren't valid without listescape */
+ if (mail_namespace_get_sep(ns) != '/' && list_sep != '/') {
+ for (p = str_c_modifiable(vname); *p != '\0'; p++) {
+ if (*p == '/')
+ *p = alt_char;
+ }
+ if (dsync_is_valid_name(ns, str_c(vname)))
+ return;
+ }
+ /* 3) probably some reserved name (e.g. dbox-Mails) */
+ str_insert(vname, 0, "_");
+ if (dsync_is_valid_name(ns, str_c(vname)))
+ return;
- output = t_strdup_noconst(input);
- for (p = output; *p != '\0'; p++) {
- if (!i_isalnum(*p))
- *p = alt_char;
- }
- return output;
-}
-
-static const char *
-dsync_fix_mailbox_name(struct mail_namespace *ns, const char *vname,
- char alt_char)
-{
- const char *name;
- char list_sep;
-
- name = mailbox_list_get_storage_name(ns->list, vname);
-
- list_sep = mailbox_list_get_hierarchy_sep(ns->list);
- if (!mailbox_list_is_valid_create_name(ns->list, name)) {
- /* change any real separators to alt separators,
- drop any potentially invalid characters */
- name = mailbox_name_cleanup(name, list_sep, alt_char);
- }
- if (!mailbox_list_is_valid_create_name(ns->list, name)) {
- /* still not working, apparently it's not valid mUTF-7.
- just drop all non-alphanumeric characters. */
- name = mailbox_name_force_cleanup(name, alt_char);
- }
- if (!mailbox_list_is_valid_create_name(ns->list, name)) {
- /* probably some reserved name (e.g. dbox-Mails) */
- name = t_strconcat("_", name, NULL);
- }
- if (!mailbox_list_is_valid_create_name(ns->list, name)) {
- /* name is too long? just give up and generate a
- unique name */
- guid_128_t guid;
-
- guid_128_generate(guid);
- name = guid_128_to_string(guid);
- }
- i_assert(mailbox_list_is_valid_create_name(ns->list, name));
- return mailbox_list_get_vname(ns->list, name);
+ /* 4) name is too long? just give up and generate a unique name */
+ guid_128_generate(guid);
+ str_truncate(vname, 0);
+ str_append(vname, guid_128_to_string(guid));
+ i_assert(dsync_is_valid_name(ns, str_c(vname)));
}
static int
@@ -264,7 +269,8 @@
}
str_truncate(vname, str_len(vname)-1);
- *name_r = dsync_fix_mailbox_name(ns, str_c(vname), alt_char);
+ dsync_fix_mailbox_name(ns, vname, alt_char);
+ *name_r = str_c(vname);
*ns_r = ns;
return 0;
}
diff -r f0d487918a2b -r 20edc46254ce src/lib-storage/list/mailbox-list-fs-iter.c
--- a/src/lib-storage/list/mailbox-list-fs-iter.c Tue Sep 25 22:51:46 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-fs-iter.c Tue Sep 25 22:53:36 2012 +0300
@@ -328,7 +328,7 @@
{
struct mailbox_list *_list = ctx->ctx.list;
ARRAY(const char *) valid_patterns;
- const char *pattern, *test_pattern, *real_pattern;
+ const char *pattern, *test_pattern, *real_pattern, *error;
unsigned int prefix_len;
prefix_len = strlen(_list->ns->prefix);
@@ -345,8 +345,8 @@
separators. */
real_pattern =
mailbox_list_get_storage_name(_list, test_pattern);
- if (mailbox_list_is_valid_pattern(_list, test_pattern) &&
- mailbox_list_is_valid_pattern(_list, real_pattern)) {
+ if (mailbox_list_is_valid_name(_list, test_pattern, &error) &&
+ mailbox_list_is_valid_name(_list, real_pattern, &error)) {
pattern = p_strdup(ctx->ctx.pool, *patterns);
array_append(&valid_patterns, &pattern, 1);
}
diff -r f0d487918a2b -r 20edc46254ce src/lib-storage/list/mailbox-list-fs.c
--- a/src/lib-storage/list/mailbox-list-fs.c Tue Sep 25 22:51:46 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-fs.c Tue Sep 25 22:53:36 2012 +0300
@@ -51,14 +51,14 @@
enum mailbox_list_path_type type)
{
const struct mailbox_list_settings *set = &_list->set;
- const char *root_dir;
+ const char *root_dir, *error;
if (name == NULL) {
/* return root directories */
return mailbox_list_set_get_root_path(set, type);
}
- i_assert(mailbox_list_is_valid_pattern(_list, name));
+ i_assert(mailbox_list_is_valid_name(_list, name, &error));
if (mailbox_list_try_get_absolute_path(_list, &name))
return name;
diff -r f0d487918a2b -r 20edc46254ce src/lib-storage/list/mailbox-list-subscriptions.c
--- a/src/lib-storage/list/mailbox-list-subscriptions.c Tue Sep 25 22:51:46 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-subscriptions.c Tue Sep 25 22:53:36 2012 +0300
@@ -27,7 +27,7 @@
struct mail_namespace *ns, *default_ns = list->ns;
struct mail_namespace *namespaces = default_ns->user->namespaces;
struct mailbox_node *node;
- const char *vname, *ns_name;
+ const char *vname, *ns_name, *error;
unsigned int len;
bool created;
@@ -87,7 +87,7 @@
name = t_strndup(name, len-1);
}
- if (!mailbox_list_is_valid_existing_name(list, name)) {
+ if (!mailbox_list_is_valid_name(list, name, &error)) {
/* we'll only get into trouble if we show this */
return -1;
} else {
@@ -246,7 +246,7 @@
struct mailbox_list *list = _ctx->list;
struct mailbox_node *node;
enum mailbox_info_flags subs_flags;
- const char *vname, *storage_name;
+ const char *vname, *storage_name, *error;
int ret;
node = mailbox_tree_iterate_next(ctx->iter, &vname);
@@ -265,7 +265,7 @@
}
storage_name = mailbox_list_get_storage_name(list, vname);
- if (!mailbox_list_is_valid_pattern(list, storage_name)) {
+ if (!mailbox_list_is_valid_name(list, storage_name, &error)) {
/* broken entry in subscriptions file */
ctx->info.flags = MAILBOX_NONEXISTENT;
} else if (mailbox_list_mailbox(list, storage_name,
diff -r f0d487918a2b -r 20edc46254ce src/lib-storage/mail-storage.c
--- a/src/lib-storage/mail-storage.c Tue Sep 25 22:51:46 2012 +0300
+++ b/src/lib-storage/mail-storage.c Tue Sep 25 22:53:36 2012 +0300
@@ -709,31 +709,42 @@
return box;
}
-static bool mailbox_name_verify_separators(const char *vname, char sep)
+static bool
+mailbox_name_verify_separators(const char *vname, char sep,
+ const char **error_r)
{
unsigned int i;
- bool prev_sep = TRUE;
+ bool prev_sep = FALSE;
+
+ if (vname[0] == sep) {
+ *error_r = "Begins with hierarchy separator";
+ return FALSE;
+ }
/* Make sure the vname is correct: non-empty, doesn't begin or end
with separator and no adjacent separators */
- for (i = 0; vname[i] != '\0'; i++) {
+ for (i = 1; vname[i] != '\0'; i++) {
if (vname[i] == sep) {
- if (prev_sep)
+ if (prev_sep) {
+ *error_r = "Has adjacent hierarchy separators";
return FALSE;
+ }
prev_sep = TRUE;
} else {
prev_sep = FALSE;
}
}
- if (prev_sep)
+ if (prev_sep) {
+ *error_r = "Ends with hierarchy separator";
return FALSE;
+ }
return TRUE;
}
static int mailbox_verify_name(struct mailbox *box)
{
struct mail_namespace *ns = box->list->ns;
- const char *vname = box->vname;
+ const char *error, *vname = box->vname;
char list_sep, ns_sep;
if (box->inbox_user) {
@@ -768,24 +779,40 @@
"Character not allowed in mailbox name: '%c'", list_sep));
return -1;
}
- if (!mailbox_name_verify_separators(box->vname, ns_sep) ||
- !mailbox_list_is_valid_existing_name(box->list, box->name)) {
+ if (!mailbox_name_verify_separators(vname, ns_sep, &error) ||
+ !mailbox_list_is_valid_name(box->list, box->name, &error)) {
mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
- "Invalid mailbox name");
+ t_strdup_printf("Invalid mailbox name: %s", error));
return -1;
}
return 0;
}
-static int mailbox_verify_create_name(struct mailbox *box)
+static bool mailbox_name_has_control_chars(const char *name)
+{
+ const char *p;
+
+ for (p = name; *p != '\0'; p++) {
+ if ((unsigned char)*p < ' ')
+ return TRUE;
+ }
+ return FALSE;
+}
More information about the dovecot-cvs
mailing list