changeset 22311:25af9d4dad59

global: Replaced t_strsplit_tab() calls with t_strsplit_tabescaped() This is useful especially in auth code to support LFs in extra fields. Other pieces of code were also tab-escaping strings, but never unescaping them. Usually it didn't matter, because nobody would use the escaped characters. Still, the code wasn't exactly behaving correctly. One downside to this change is that it's now possible to pass through TABs, CRs and LFs through the various protocols. In theory this shouldn't cause any problems, but combined with other bugs this could trigger some security problems.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Thu, 20 Oct 2016 17:45:44 +0300
parents a28f5bfb15fc
children 19f52d0ede61
files src/anvil/anvil-connection.c src/auth/auth-fields.c src/auth/auth-master-connection.c src/auth/passdb-blocking.c src/auth/passdb-cache.c src/config/config-connection.c src/director/director-connection.c src/director/director-test.c src/director/login-connection.c src/doveadm/doveadm-director.c src/doveadm/doveadm-penalty.c src/doveadm/doveadm-proxy.c src/doveadm/doveadm-replicator.c src/doveadm/doveadm-who.c src/doveadm/dsync/dsync-ibc-stream.c src/ipc/ipc-connection.c src/lib-auth/auth-master.c src/lib-auth/auth-server-connection.c src/lib-master/master-login-auth.c src/lib-master/master-service-settings.c src/login-common/login-proxy.c src/plugins/push-notification/push-notification-driver-ox.c
diffstat 22 files changed, 44 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/src/anvil/anvil-connection.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/anvil/anvil-connection.c	Thu Oct 20 17:45:44 2016 +0300
@@ -4,6 +4,7 @@
 #include "llist.h"
 #include "istream.h"
 #include "ostream.h"
+#include "strescape.h"
 #include "master-service.h"
 #include "master-interface.h"
 #include "connect-limit.h"
@@ -39,7 +40,7 @@
 	const char *line;
 
 	line = i_stream_next_line(conn->input);
-	return line == NULL ? NULL : t_strsplit_tab(line);
+	return line == NULL ? NULL : t_strsplit_tabescaped(line);
 }
 
 static int
--- a/src/auth/auth-fields.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/auth/auth-fields.c	Thu Oct 20 17:45:44 2016 +0300
@@ -118,7 +118,7 @@
 				 const char *str, enum auth_field_flags flags)
 {
 	T_BEGIN {
-		const char *const *arg = t_strsplit_tab(str);
+		const char *const *arg = t_strsplit_tabescaped(str);
 		const char *key, *value;
 
 		for (; *arg != NULL; arg++) {
--- a/src/auth/auth-master-connection.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/auth/auth-master-connection.c	Thu Oct 20 17:45:44 2016 +0300
@@ -95,7 +95,7 @@
 	buffer_t buf;
 
 	/* <id> <client-pid> <client-id> <cookie> [<parameters>] */
-	list = t_strsplit_tab(args);
+	list = t_strsplit_tabescaped(args);
 	if (str_array_length(list) < 4 ||
 	    str_to_uint(list[0], &id) < 0 ||
 	    str_to_uint(list[1], &client_pid) < 0 ||
@@ -139,7 +139,7 @@
 	unsigned int count;
 
 	/* <id> [<user> [<user> [..]] */
-	list = t_strsplit_tab(args);
+	list = t_strsplit_tabescaped(args);
 	if (list[0] == NULL) {
 		i_error("BUG: doveadm sent broken CACHE-FLUSH");
 		return FALSE;
@@ -169,7 +169,7 @@
 	unsigned int id;
 
 	/* <id> <userid> [<parameters>] */
-	list = t_strsplit_tab(args);
+	list = t_strsplit_tabescaped(args);
 	if (list[0] == NULL || list[1] == NULL ||
 	    str_to_uint(list[0], &id) < 0) {
 		i_error("BUG: Master sent broken %s", cmd);
@@ -531,7 +531,7 @@
 	unsigned int id;
 
 	/* <id> [<parameters>] */
-	list = t_strsplit_tab(args);
+	list = t_strsplit_tabescaped(args);
 	if (list[0] == NULL || str_to_uint(list[0], &id) < 0) {
 		i_error("BUG: Master sent broken LIST");
 		return FALSE;
--- a/src/auth/passdb-blocking.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/auth/passdb-blocking.c	Thu Oct 20 17:45:44 2016 +0300
@@ -27,7 +27,7 @@
 	enum passdb_result ret;
 	const char *const *args;
 
-	args = t_strsplit_tab(reply);
+	args = t_strsplit_tabescaped(reply);
 
 	if (strcmp(*args, "OK") == 0 && args[1] != NULL && args[2] != NULL) {
 		/* OK \t user \t password [\t extra] */
--- a/src/auth/passdb-cache.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/auth/passdb-cache.c	Thu Oct 20 17:45:44 2016 +0300
@@ -1,6 +1,7 @@
 /* Copyright (c) 2004-2017 Dovecot authors, see the included COPYING file */
 
 #include "auth-common.h"
+#include "strescape.h"
 #include "restrict-process-size.h"
 #include "auth-request-stats.h"
 #include "password-scheme.h"
@@ -72,7 +73,7 @@
 		return TRUE;
 	}
 
-	list = t_strsplit_tab(value);
+	list = t_strsplit_tabescaped(value);
 
 	cached_pw = list[0];
 	if (*cached_pw == '\0') {
@@ -132,7 +133,7 @@
 		return TRUE;
 	}
 
-	list = t_strsplit_tab(value);
+	list = t_strsplit_tabescaped(value);
 	auth_request_set_fields(request, list + 1, NULL);
 
 	*result_r = PASSDB_RESULT_OK;
--- a/src/config/config-connection.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/config/config-connection.c	Thu Oct 20 17:45:44 2016 +0300
@@ -5,6 +5,7 @@
 #include "llist.h"
 #include "istream.h"
 #include "ostream.h"
+#include "strescape.h"
 #include "settings-parser.h"
 #include "master-service.h"
 #include "master-service-settings.h"
@@ -42,7 +43,7 @@
 	if (line == NULL)
 		return NULL;
 
-	return t_strsplit_tab(line);
+	return t_strsplit_tabescaped(line);
 }
 
 static void
--- a/src/director/director-connection.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/director/director-connection.c	Thu Oct 20 17:45:44 2016 +0300
@@ -1739,7 +1739,7 @@
 
 	dir_debug("input: %s: %s", conn->name, line);
 
-	args = t_strsplit_tab(line);
+	args = t_strsplit_tabescaped(line);
 	cmd = args[0]; args++;
 	if (cmd == NULL) {
 		director_cmd_error(conn, "Received empty line");
--- a/src/director/director-test.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/director/director-test.c	Thu Oct 20 17:45:44 2016 +0300
@@ -22,6 +22,7 @@
 #include "write-full.h"
 #include "hash.h"
 #include "llist.h"
+#include "strescape.h"
 #include "imap-parser.h"
 #include "master-service.h"
 #include "master-service-settings.h"
@@ -497,7 +498,7 @@
 			break;
 		/* ip vhost-count user-count */
 		T_BEGIN {
-			const char *const *args = t_strsplit_tab(line);
+			const char *const *args = t_strsplit_tabescaped(line);
 			struct host *host;
 
 			host = i_new(struct host, 1);
--- a/src/director/login-connection.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/director/login-connection.c	Thu Oct 20 17:45:44 2016 +0300
@@ -7,6 +7,7 @@
 #include "istream.h"
 #include "ostream.h"
 #include "llist.h"
+#include "strescape.h"
 #include "master-service.h"
 #include "director.h"
 #include "director-request.h"
@@ -199,7 +200,7 @@
 	}
 
 	/* OK <id> [<parameters>] */
-	args = t_strsplit_tab(line_params);
+	args = t_strsplit_tabescaped(line_params);
 	if (*args != NULL) {
 		/* we should always get here, but in case we don't just
 		   forward as-is and let login process handle the error. */
--- a/src/doveadm/doveadm-director.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/doveadm/doveadm-director.c	Thu Oct 20 17:45:44 2016 +0300
@@ -152,7 +152,7 @@
 		return;
 	}
 
-	args = t_strsplit_tab(line);
+	args = t_strsplit_tabescaped(line);
 	if (str_array_length(args) != 4 ||
 	    str_to_uint(args[1], &expires) < 0) {
 		i_error("Invalid reply from director");
@@ -211,7 +211,7 @@
 			unsigned int arg_count;
 			time_t ts;
 
-			args = t_strsplit_tab(line);
+			args = t_strsplit_tabescaped(line);
 			arg_count = str_array_length(args);
 			if (arg_count >= 6) {
 				/* ip vhosts users tag updown updown-ts */
@@ -391,7 +391,7 @@
 		if (*line == '\0')
 			break;
 		T_BEGIN {
-			args = t_strsplit_tab(line);
+			args = t_strsplit_tabescaped(line);
 			if (str_array_length(args) < 3 ||
 			    str_to_uint(args[0], &user_hash) < 0 ||
 			    str_to_uint(args[1], &expires) < 0 ||
@@ -755,7 +755,7 @@
 		if (*line == '\0')
 			break;
 		T_BEGIN {
-			args = t_strsplit_tab(line);
+			args = t_strsplit_tabescaped(line);
 			if (str_array_length(args) >= 2) {
 				const char *host = args[0];
 				const char *tag = args[3];
@@ -874,7 +874,7 @@
 		if (*line == '\0')
 			break;
 		T_BEGIN {
-			args = t_strsplit_tab(line);
+			args = t_strsplit_tabescaped(line);
 			if (str_array_length(args) >= 5 &&
 			    str_to_ulong(args[3], &l) == 0) {
 				doveadm_print(args[0]);
--- a/src/doveadm/doveadm-penalty.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/doveadm/doveadm-penalty.c	Thu Oct 20 17:45:44 2016 +0300
@@ -5,6 +5,7 @@
 #include "net.h"
 #include "istream.h"
 #include "hash.h"
+#include "strescape.h"
 #include "time-util.h"
 #include "doveadm.h"
 #include "doveadm-print.h"
@@ -26,7 +27,7 @@
 
 static void penalty_parse_line(const char *line, struct penalty_line *line_r)
 {
-	const char *const *args = t_strsplit_tab(line);
+	const char *const *args = t_strsplit_tabescaped(line);
 	const char *ident = args[0];
 	const char *penalty_str = args[1];
 	const char *last_penalty_str = args[2];
--- a/src/doveadm/doveadm-proxy.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/doveadm/doveadm-proxy.c	Thu Oct 20 17:45:44 2016 +0300
@@ -85,7 +85,7 @@
 
 	switch (state) {
 	case IPC_CLIENT_CMD_STATE_REPLY: {
-		const char *const *args = t_strsplit_tab(data);
+		const char *const *args = t_strsplit_tabescaped(data);
 
 		if (!*seen_header) {
 			cmd_proxy_list_header(args);
--- a/src/doveadm/doveadm-replicator.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/doveadm/doveadm-replicator.c	Thu Oct 20 17:45:44 2016 +0300
@@ -167,7 +167,7 @@
 		if (*line == '\0')
 			break;
 		T_BEGIN {
-			args = t_strsplit_tab(line);
+			args = t_strsplit_tabescaped(line);
 			if (str_array_length(args) >= 5 &&
 			    str_to_time(args[2], &last_fast) == 0 &&
 			    str_to_time(args[3], &last_full) == 0 &&
@@ -207,7 +207,7 @@
 		if (*line == '\0')
 			break;
 		T_BEGIN {
-			const char *const *args = t_strsplit_tab(line);
+			const char *const *args = t_strsplit_tabescaped(line);
 
 			for (i = 0; i < 3; i++) {
 				if (args[i] == NULL)
--- a/src/doveadm/doveadm-who.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/doveadm/doveadm-who.c	Thu Oct 20 17:45:44 2016 +0300
@@ -7,6 +7,7 @@
 #include "wildcard-match.h"
 #include "hash.h"
 #include "str.h"
+#include "strescape.h"
 #include "doveadm.h"
 #include "doveadm-print.h"
 #include "doveadm-who.h"
@@ -79,7 +80,7 @@
 
 static int who_parse_line(const char *line, struct who_line *line_r)
 {
-	const char *const *args = t_strsplit_tab(line);
+	const char *const *args = t_strsplit_tabescaped(line);
 	const char *ident = args[0];
 	const char *pid_str = args[1];
 	const char *refcount_str = args[2];
--- a/src/doveadm/dsync/dsync-ibc-stream.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/doveadm/dsync/dsync-ibc-stream.c	Thu Oct 20 17:45:44 2016 +0300
@@ -1775,7 +1775,7 @@
 
 	if (dsync_deserializer_decode_try(decoder, "keyword_changes", &value) &&
 	    *value != '\0') {
-		const char *const *changes = t_strsplit_tab(value);
+		const char *const *changes = t_strsplit_tabescaped(value);
 		unsigned int i, count = str_array_length(changes);
 
 		p_array_init(&change->keyword_changes, pool, count);
--- a/src/ipc/ipc-connection.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/ipc/ipc-connection.c	Thu Oct 20 17:45:44 2016 +0300
@@ -6,6 +6,7 @@
 #include "istream.h"
 #include "ostream.h"
 #include "llist.h"
+#include "strescape.h"
 #include "master-service.h"
 #include "ipc-group.h"
 #include "ipc-connection.h"
@@ -127,7 +128,7 @@
 		if ((line = i_stream_next_line(conn->input)) == NULL)
 			return;
 
-		args = t_strsplit_tab(line);
+		args = t_strsplit_tabescaped(line);
 		if (str_array_length(args) < 3 ||
 		    strcmp(args[0], "HANDSHAKE") != 0) {
 			i_error("IPC server sent invalid handshake");
--- a/src/lib-auth/auth-master.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/lib-auth/auth-master.c	Thu Oct 20 17:45:44 2016 +0300
@@ -120,7 +120,7 @@
 	const char *line, *const *tmp;
 
 	while ((line = i_stream_next_line(conn->input)) != NULL) {
-		tmp = t_strsplit_tab(line);
+		tmp = t_strsplit_tabescaped(line);
 		if (strcmp(tmp[0], "VERSION") == 0 &&
 		    tmp[1] != NULL && tmp[2] != NULL) {
 			if (strcmp(tmp[1], dec2str(AUTH_PROTOCOL_MAJOR)) != 0) {
--- a/src/lib-auth/auth-server-connection.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/lib-auth/auth-server-connection.c	Thu Oct 20 17:45:44 2016 +0300
@@ -8,6 +8,7 @@
 #include "istream.h"
 #include "ostream.h"
 #include "net.h"
+#include "strescape.h"
 #include "eacces-error.h"
 #include "auth-client-private.h"
 #include "auth-client-request.h"
@@ -206,7 +207,7 @@
 	if (conn->client->debug)
 		i_debug("auth input: %s", line);
 
-	args = t_strsplit_tab(line);
+	args = t_strsplit_tabescaped(line);
 	if (args[0] == NULL) {
 		i_error("Auth server sent empty line");
 		return -1;
--- a/src/lib-master/master-login-auth.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/lib-master/master-login-auth.c	Thu Oct 20 17:45:44 2016 +0300
@@ -10,6 +10,7 @@
 #include "hex-binary.h"
 #include "hash.h"
 #include "str.h"
+#include "strescape.h"
 #include "master-interface.h"
 #include "master-service.h"
 #include "master-auth.h"
@@ -232,7 +233,7 @@
 
 	/* <id> <userid> [..] */
 
-	list = t_strsplit_tab(args);
+	list = t_strsplit_tabescaped(args);
 	if (list[0] == NULL || list[1] == NULL ||
 	    str_to_uint(list[0], &id) < 0) {
 		i_error("Auth server sent corrupted USER line");
@@ -278,7 +279,7 @@
  	const char *const *args, *error = NULL;
 	unsigned int i, id;
 
-	args = t_strsplit_tab(args_line);
+	args = t_strsplit_tabescaped(args_line);
 	if (args[0] == NULL || str_to_uint(args[0], &id) < 0) {
 		i_error("Auth server sent broken FAIL line");
 		return FALSE;
--- a/src/lib-master/master-service-settings.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/lib-master/master-service-settings.c	Thu Oct 20 17:45:44 2016 +0300
@@ -6,6 +6,7 @@
 #include "istream.h"
 #include "write-full.h"
 #include "str.h"
+#include "strescape.h"
 #include "syslog-util.h"
 #include "eacces-error.h"
 #include "env-util.h"
@@ -334,7 +335,7 @@
 	}
 
 	T_BEGIN {
-		const char *const *arg = t_strsplit_tab(line);
+		const char *const *arg = t_strsplit_tabescaped(line);
 		ARRAY_TYPE(const_string) services;
 
 		p_array_init(&services, pool, 8);
--- a/src/login-common/login-proxy.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/login-common/login-proxy.c	Thu Oct 20 17:45:44 2016 +0300
@@ -1026,7 +1026,7 @@
 
 static void login_proxy_ipc_cmd(struct ipc_cmd *cmd, const char *line)
 {
-	const char *const *args = t_strsplit_tab(line);
+	const char *const *args = t_strsplit_tabescaped(line);
 	const char *name = args[0];
 
 	args++;
--- a/src/plugins/push-notification/push-notification-driver-ox.c	Wed May 17 12:26:42 2017 +0300
+++ b/src/plugins/push-notification/push-notification-driver-ox.c	Thu Oct 20 17:45:44 2016 +0300
@@ -11,6 +11,7 @@
 #include "mailbox-attribute.h"
 #include "mail-storage-private.h"
 #include "str.h"
+#include "strescape.h"
 
 #include "push-notification-drivers.h"
 #include "push-notification-event-messagenew.h"
@@ -249,7 +250,7 @@
     txn = p_new(dtxn->ptxn->pool, struct push_notification_driver_ox_txn, 1);
 
     /* Valid keys: user */
-    args = t_strsplit_tab(md_value);
+    args = t_strsplit_tabescaped(md_value);
     for (; *args != NULL; args++) {
         key = *args;