dovecot: mailbox_keywords_create() checks keyword validity now a...

dovecot at dovecot.org dovecot at dovecot.org
Sun Sep 2 06:10:58 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/23c9ac999578
changeset: 6353:23c9ac999578
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Sep 02 06:10:54 2007 +0300
description:
mailbox_keywords_create() checks keyword validity now and returns failure if
any of them are invalid. Added mailbox_keywords_create_valid() that only
drops invalid keywords. Removed mbox and IMAP-specific keyword checks, they
all use the same checking now.

diffstat:

14 files changed, 158 insertions(+), 98 deletions(-)
src/deliver/deliver.c                        |    2 
src/imap/cmd-append.c                        |    9 ++
src/imap/cmd-copy.c                          |    2 
src/imap/cmd-store.c                         |   10 ++-
src/imap/commands-util.c                     |   57 +++--------------
src/imap/common.h                            |    3 
src/imap/main.c                              |    6 -
src/lib-storage/index/index-storage.c        |   83 ++++++++++++++++++++++++--
src/lib-storage/index/index-storage.h        |    8 +-
src/lib-storage/index/mbox/mbox-sync-parse.c |   18 -----
src/lib-storage/mail-storage-private.h       |   10 +--
src/lib-storage/mail-storage.c               |   34 +++++++++-
src/lib-storage/mail-storage.h               |   11 ++-
src/plugins/convert/convert-storage.c        |    3 

diffs (truncated from 482 to 300 lines):

diff -r 0f1a4b7b39a3 -r 23c9ac999578 src/deliver/deliver.c
--- a/src/deliver/deliver.c	Sun Sep 02 06:08:58 2007 +0300
+++ b/src/deliver/deliver.c	Sun Sep 02 06:10:54 2007 +0300
@@ -142,7 +142,7 @@ int deliver_save(struct mail_namespace *
 	t = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_EXTERNAL);
 
 	kw = strarray_length(keywords) == 0 ? NULL :
-		mailbox_keywords_create(t, keywords);
+		mailbox_keywords_create_valid(t, keywords);
 	if (mailbox_copy(t, mail, flags, kw, NULL) < 0)
 		ret = -1;
 	mailbox_keywords_free(t, &kw);
diff -r 0f1a4b7b39a3 -r 23c9ac999578 src/imap/cmd-append.c
--- a/src/imap/cmd-append.c	Sun Sep 02 06:08:58 2007 +0300
+++ b/src/imap/cmd-append.c	Sun Sep 02 06:10:54 2007 +0300
@@ -290,8 +290,13 @@ static bool cmd_append_continue_parsing(
 		if (!client_parse_mail_flags(cmd, flags_list,
 					     &flags, &keywords_list))
 			return cmd_append_cancel(ctx, nonsync);
-		keywords = keywords_list == NULL ? NULL :
-			mailbox_keywords_create(ctx->t, keywords_list);
+		if (keywords_list == NULL)
+			keywords = NULL;
+		else if (mailbox_keywords_create(ctx->t, keywords_list,
+						 &keywords) < 0) {
+			client_send_storage_error(cmd, ctx->storage);
+			return cmd_append_cancel(ctx, nonsync);
+		}
 	} else {
 		flags = 0;
 		keywords = NULL;
diff -r 0f1a4b7b39a3 -r 23c9ac999578 src/imap/cmd-copy.c
--- a/src/imap/cmd-copy.c	Sun Sep 02 06:08:58 2007 +0300
+++ b/src/imap/cmd-copy.c	Sun Sep 02 06:10:54 2007 +0300
@@ -62,7 +62,7 @@ static int fetch_and_copy(struct client 
 
 		keywords_list = mail_get_keywords(mail);
 		keywords = strarray_length(keywords_list) == 0 ? NULL :
-			mailbox_keywords_create(t, keywords_list);
+			mailbox_keywords_create_valid(t, keywords_list);
 		if (mailbox_copy(t, mail, mail_get_flags(mail),
 				 keywords, NULL) < 0)
 			ret = mail->expunged ? 0 : -1;
diff -r 0f1a4b7b39a3 -r 23c9ac999578 src/imap/cmd-store.c
--- a/src/imap/cmd-store.c	Sun Sep 02 06:08:58 2007 +0300
+++ b/src/imap/cmd-store.c	Sun Sep 02 06:10:54 2007 +0300
@@ -88,8 +88,14 @@ bool cmd_store(struct client_command_con
 
 	t = mailbox_transaction_begin(box, !silent ? 0 :
 				      MAILBOX_TRANSACTION_FLAG_HIDE);
-	keywords = keywords_list != NULL || modify_type == MODIFY_REPLACE ?
-		mailbox_keywords_create(t, keywords_list) : NULL;
+	if (keywords_list == NULL && modify_type != MODIFY_REPLACE)
+		keywords = NULL;
+	else if (mailbox_keywords_create(t, keywords_list, &keywords) < 0) {
+		/* invalid keywords */
+		mailbox_transaction_rollback(&t);
+		client_send_storage_error(cmd, mailbox_get_storage(box));
+		return TRUE;
+	}
 	search_ctx = mailbox_search_init(t, NULL, search_arg, NULL);
 
 	mail = mail_alloc(t, MAIL_FETCH_FLAGS, NULL);
diff -r 0f1a4b7b39a3 -r 23c9ac999578 src/imap/commands-util.c
--- a/src/imap/commands-util.c	Sun Sep 02 06:08:58 2007 +0300
+++ b/src/imap/commands-util.c	Sun Sep 02 06:10:54 2007 +0300
@@ -189,45 +189,17 @@ void client_send_untagged_storage_error(
 	client_send_line(client, t_strconcat("* NO ", error_string, NULL));
 }
 
-static bool is_valid_keyword(struct client_command_context *cmd,
-			     const char *keyword)
-{
-	const char *const *names;
-	unsigned int i, count;
-
-	/* if it already exists, skip validity checks */
-	if (array_is_created(&cmd->client->keywords.keywords)) {
-		names = array_get(&cmd->client->keywords.keywords, &count);
-		for (i = 0; i < count; i++) {
-			if (strcasecmp(names[i], keyword) == 0)
-				return TRUE;
-		}
-	}
-
-	if (strlen(keyword) > max_keyword_length) {
-		client_send_tagline(cmd,
-			t_strdup_printf("BAD Invalid keyword name '%s': "
-					"Maximum length is %u characters",
-					keyword, max_keyword_length));
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
 bool client_parse_mail_flags(struct client_command_context *cmd,
 			     const struct imap_arg *args,
 			     enum mail_flags *flags_r,
 			     const char *const **keywords_r)
 {
-	const char *const *keywords;
 	const char *atom;
-	buffer_t *buffer;
-	size_t size, i;
+	ARRAY_DEFINE(keywords, const char *);
 
 	*flags_r = 0;
 	*keywords_r = NULL;
-	buffer = buffer_create_dynamic(cmd->pool, 256);
+	p_array_init(&keywords, cmd->pool, 16);
 
 	while (args->type != IMAP_ARG_EOL) {
 		if (args->type != IMAP_ARG_ATOM) {
@@ -257,28 +229,19 @@ bool client_parse_mail_flags(struct clie
 				return FALSE;
 			}
 		} else {
-			/* keyword - first make sure it's not a duplicate */
-			keywords = buffer_get_data(buffer, &size);
-			size /= sizeof(const char *);
-			for (i = 0; i < size; i++) {
-				if (strcasecmp(keywords[i], atom) == 0)
-					break;
-			}
-
-			if (i == size) {
-				if (!is_valid_keyword(cmd, atom))
-					return FALSE;
-				buffer_append(buffer, &atom, sizeof(atom));
-			}
+			/* keyword validity checks are done by lib-storage */
+			array_append(&keywords, &atom, 1);
 		}
 
 		args++;
 	}
 
-	atom = NULL;
-	buffer_append(buffer, &atom, sizeof(atom));
-	*keywords_r = buffer->used == sizeof(atom) ? NULL :
-		buffer_get_data(buffer, NULL);
+	if (array_count(&keywords) == 0)
+		*keywords_r = NULL;
+	else {
+		(void)array_append_space(&keywords); /* NULL-terminate */
+		*keywords_r = array_idx(&keywords, 0);
+	}
 	return TRUE;
 }
 
diff -r 0f1a4b7b39a3 -r 23c9ac999578 src/imap/common.h
--- a/src/imap/common.h	Sun Sep 02 06:08:58 2007 +0300
+++ b/src/imap/common.h	Sun Sep 02 06:10:54 2007 +0300
@@ -21,8 +21,6 @@
    by default. */
 #define DEFAULT_IMAP_MAX_LINE_LENGTH 65536
 
-#define DEFAULT_MAX_KEYWORD_LENGTH 50
-
 enum client_workarounds {
 	WORKAROUND_DELAY_NEWMAIL		= 0x01,
 	WORKAROUND_NETSCAPE_EOH			= 0x04,
@@ -30,7 +28,6 @@ enum client_workarounds {
 };
 
 extern struct ioloop *ioloop;
-extern unsigned int max_keyword_length;
 extern unsigned int imap_max_line_length;
 extern enum client_workarounds client_workarounds;
 extern const char *logout_format;
diff -r 0f1a4b7b39a3 -r 23c9ac999578 src/imap/main.c
--- a/src/imap/main.c	Sun Sep 02 06:08:58 2007 +0300
+++ b/src/imap/main.c	Sun Sep 02 06:10:54 2007 +0300
@@ -39,7 +39,6 @@ struct client_workaround_list client_wor
 };
 
 struct ioloop *ioloop;
-unsigned int max_keyword_length;
 unsigned int imap_max_line_length;
 enum client_workarounds client_workarounds = 0;
 const char *logout_format;
@@ -225,11 +224,6 @@ static void main_init(void)
 		(unsigned int)strtoul(str, NULL, 10) :
 		DEFAULT_IMAP_MAX_LINE_LENGTH;
 
-	str = getenv("MAIL_MAX_KEYWORD_LENGTH");
-	max_keyword_length = str != NULL ?
-		(unsigned int)strtoul(str, NULL, 10) :
-		DEFAULT_MAX_KEYWORD_LENGTH;
-
 	logout_format = getenv("IMAP_LOGOUT_FORMAT");
 	if (logout_format == NULL)
 		logout_format = "bytes=%i/%o";
diff -r 0f1a4b7b39a3 -r 23c9ac999578 src/lib-storage/index/index-storage.c
--- a/src/lib-storage/index/index-storage.c	Sun Sep 02 06:08:58 2007 +0300
+++ b/src/lib-storage/index/index-storage.c	Sun Sep 02 06:10:54 2007 +0300
@@ -4,6 +4,7 @@
 #include "array.h"
 #include "buffer.h"
 #include "ioloop.h"
+#include "imap-parser.h"
 #include "mkdir-parents.h"
 #include "mail-index-private.h"
 #include "index-storage.h"
@@ -469,14 +470,86 @@ void mail_storage_set_index_error(struct
 	mail_index_reset_error(ibox->index);
 }
 
-struct mail_keywords *
-index_keywords_create(struct mailbox_transaction_context *_t,
-		      const char *const keywords[])
+int index_mailbox_keyword_is_valid(struct index_mailbox *ibox,
+				   const char *keyword, const char **error_r)
+{
+	unsigned int i, idx;
+
+	/* if it already exists, skip validity checks */
+	if (mail_index_keyword_lookup(ibox->index, keyword, &idx))
+		return TRUE;
+
+	if (*keyword == '\0') {
+		*error_r = "Empty keywords not allowed";
+		return FALSE;
+	}
+
+	/* these are IMAP-specific restrictions, but for now IMAP is all we
+	   care about */
+	for (i = 0; keyword[i] != '\0'; i++) {
+		if (IS_ATOM_SPECIAL((unsigned char)keyword[i])) {
+			*error_r = "Invalid characters in keyword";
+			return FALSE;
+		}
+		if ((unsigned char)keyword[i] >= 0x80) {
+			*error_r = "8bit characters in keyword";
+			return FALSE;
+		}
+	}
+	if (i > ibox->box.storage->keyword_max_len) {
+		*error_r = "Keyword length too long";
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static struct mail_keywords *
+index_keywords_create_skip(struct index_transaction_context *t,
+			   const char *const keywords[])
+{
+	ARRAY_DEFINE(valid_keywords, const char *);
+	struct mail_keywords *kw;
+	const char *error;
+
+	t_push();
+	t_array_init(&valid_keywords, 32);
+	for (; *keywords != NULL; keywords++) {
+		if (index_mailbox_keyword_is_valid(t->ibox, *keywords, &error))
+			array_append(&valid_keywords, keywords, 1);
+	}
+	(void)array_append_space(&valid_keywords); /* NULL-terminate */
+	kw = mail_index_keywords_create(t->trans, keywords);
+	t_pop();
+	return kw;
+}
+
+int index_keywords_create(struct mailbox_transaction_context *_t,
+			  const char *const keywords[],
+			  struct mail_keywords **keywords_r, bool skip_invalid)
 {
 	struct index_transaction_context *t =
 		(struct index_transaction_context *)_t;
-
-	return mail_index_keywords_create(t->trans, keywords);
+	const char *error;
+	unsigned int i;
+
+	for (i = 0; keywords[i] != NULL; i++) {
+		if (!index_mailbox_keyword_is_valid(t->ibox, keywords[i],
+						    &error)) {
+			if (skip_invalid) {
+				/* found invalid keywords, do this the slow
+				   way */
+				*keywords_r =
+					index_keywords_create_skip(t, keywords);
+				return 0;
+			}
+			mail_storage_set_error(t->ibox->box.storage,
+					       MAIL_ERROR_PARAMS, error);
+			return -1;
+		}
+	}
+
+	*keywords_r = mail_index_keywords_create(t->trans, keywords);
+	return 0;
 }
 
 void index_keywords_free(struct mailbox_transaction_context *t __attr_unused__,
diff -r 0f1a4b7b39a3 -r 23c9ac999578 src/lib-storage/index/index-storage.h
--- a/src/lib-storage/index/index-storage.h	Sun Sep 02 06:08:58 2007 +0300
+++ b/src/lib-storage/index/index-storage.h	Sun Sep 02 06:10:54 2007 +0300


More information about the dovecot-cvs mailing list