dovecot-2.2: checkpassword: Escape transferred extra fields prop...

dovecot at dovecot.org dovecot at dovecot.org
Sun May 20 03:26:27 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/e5ed29ef593e
changeset: 14314:e5ed29ef593e
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Mar 10 14:11:32 2012 +0200
description:
checkpassword: Escape transferred extra fields properly.

diffstat:

 src/auth/auth-request.c         |  30 ++++++++++++++++++------------
 src/auth/auth-request.h         |   3 +++
 src/auth/checkpassword-reply.c  |  14 +++++++++++---
 src/auth/db-checkpassword.c     |  20 ++++++++++----------
 src/auth/db-checkpassword.h     |   1 +
 src/auth/passdb-checkpassword.c |   5 ++++-
 src/auth/userdb-checkpassword.c |   8 ++++++++
 7 files changed, 55 insertions(+), 26 deletions(-)

diffs (240 lines):

diff -r e3c1f3f93add -r e5ed29ef593e src/auth/auth-request.c
--- a/src/auth/auth-request.c	Sat Mar 10 13:49:12 2012 +0200
+++ b/src/auth/auth-request.c	Sat Mar 10 14:11:32 2012 +0200
@@ -1287,25 +1287,31 @@
 	}
 }
 
+void auth_request_set_field_keyvalue(struct auth_request *request,
+				     const char *field,
+				     const char *default_scheme)
+{
+	const char *key, *value;
+
+	value = strchr(field, '=');
+	if (value == NULL) {
+		key = field;
+		value = "";
+	} else {
+		key = t_strdup_until(field, value);
+		value++;
+	}
+	auth_request_set_field(request, key, value, default_scheme);
+}
+
 void auth_request_set_fields(struct auth_request *request,
 			     const char *const *fields,
 			     const char *default_scheme)
 {
-	const char *key, *value;
-
 	for (; *fields != NULL; fields++) {
 		if (**fields == '\0')
 			continue;
-
-		value = strchr(*fields, '=');
-		if (value == NULL) {
-			key = *fields;
-			value = "";
-		} else {
-			key = t_strdup_until(*fields, value);
-			value++;
-		}
-		auth_request_set_field(request, key, value, default_scheme);
+		auth_request_set_field_keyvalue(request, *fields, default_scheme);
 	}
 }
 
diff -r e3c1f3f93add -r e5ed29ef593e src/auth/auth-request.h
--- a/src/auth/auth-request.h	Sat Mar 10 13:49:12 2012 +0200
+++ b/src/auth/auth-request.h	Sat Mar 10 14:11:32 2012 +0200
@@ -171,6 +171,9 @@
 void auth_request_set_field(struct auth_request *request,
 			    const char *name, const char *value,
 			    const char *default_scheme);
+void auth_request_set_field_keyvalue(struct auth_request *request,
+				     const char *field,
+				     const char *default_scheme);
 void auth_request_set_fields(struct auth_request *request,
 			     const char *const *fields,
 			     const char *default_scheme);
diff -r e3c1f3f93add -r e5ed29ef593e src/auth/checkpassword-reply.c
--- a/src/auth/checkpassword-reply.c	Sat Mar 10 13:49:12 2012 +0200
+++ b/src/auth/checkpassword-reply.c	Sat Mar 10 14:11:32 2012 +0200
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "str.h"
+#include "strescape.h"
 #include "write-full.h"
 
 #include <stdlib.h>
@@ -23,7 +24,9 @@
 			i_error("checkpassword: USER contains TAB");
 			return 1;
 		}
-		str_printfa(str, "user=%s\t", user);
+		str_printfa(str, "user=");
+		str_tabescape_write(str, user);
+		str_append_c(str, '\t');
 	}
 
 	home = getenv("HOME");
@@ -32,7 +35,9 @@
 			i_error("checkpassword: HOME contains TAB");
 			return 1;
 		}
-		str_printfa(str, "userdb_home=%s\t", home);
+		str_printfa(str, "userdb_home=");
+		str_tabescape_write(str, home);
+		str_append_c(str, '\t');
 	}
 
 	extra_env = getenv("EXTRA");
@@ -45,7 +50,10 @@
 					uid_found = TRUE;
 				else if (strcmp(key, "userdb_gid") == 0)
 					gid_found = TRUE;
-				str_printfa(str, "%s=%s\t", key, value);
+				str_tabescape_write(str, key);
+				str_append_c(str, '=');
+				str_tabescape_write(str, value);
+				str_append_c(str, '\t');
 			}
 		}
 	}
diff -r e3c1f3f93add -r e5ed29ef593e src/auth/db-checkpassword.c
--- a/src/auth/db-checkpassword.c	Sat Mar 10 13:49:12 2012 +0200
+++ b/src/auth/db-checkpassword.c	Sat Mar 10 14:11:32 2012 +0200
@@ -12,6 +12,7 @@
 #include "execv-const.h"
 #include "env-util.h"
 #include "safe-memset.h"
+#include "strescape.h"
 #include "child-wait.h"
 #include "var-expand.h"
 #include "db-checkpassword.h"
@@ -107,9 +108,13 @@
 				 enum db_checkpassword_status status)
 {
 	struct chkpw_auth_request *request = *_request;
+	const char *const *extra_fields;
 
 	*_request = NULL;
-	request->callback(request->request, status, request->context);
+
+	extra_fields = t_strsplit_tabescaped(str_c(request->input_buf));
+	request->callback(request->request, status, extra_fields,
+			  request->context);
 	checkpassword_request_free(&request);
 }
 
@@ -148,9 +153,6 @@
 			checkpassword_internal_failure(&request);
 			break;
 		}
-
-		auth_request_set_fields(request->request,
-			t_strsplit(str_c(request->input_buf), "\t"), NULL);
 		checkpassword_finish(&request, DB_CHECKPASSWORD_STATUS_OK);
 		break;
 	case 2:
@@ -192,9 +194,6 @@
 			checkpassword_internal_failure(&request);
 			break;
 		}
-
-		auth_request_set_fields(request->request,
-			t_strsplit(str_c(request->input_buf), "\t"), NULL);
 		checkpassword_finish(&request, DB_CHECKPASSWORD_STATUS_OK);
 		break;
 	default:
@@ -457,7 +456,8 @@
 		auth_request_log_info(request, "checkpassword",
 			"Username+password combination too long (%u bytes)",
 			output_len);
-		callback(request, DB_CHECKPASSWORD_STATUS_FAILURE, context);
+		callback(request, DB_CHECKPASSWORD_STATUS_FAILURE,
+			 NULL, context);
 		return;
 	}
 
@@ -470,7 +470,7 @@
 			(void)close(fd_in[1]);
 		}
 		callback(request, DB_CHECKPASSWORD_STATUS_INTERNAL_FAILURE,
-			 context);
+			 NULL, context);
 		return;
 	}
 
@@ -483,7 +483,7 @@
 		(void)close(fd_out[0]);
 		(void)close(fd_out[1]);
 		callback(request, DB_CHECKPASSWORD_STATUS_INTERNAL_FAILURE,
-			 context);
+			 NULL, context);
 		return;
 	}
 
diff -r e3c1f3f93add -r e5ed29ef593e src/auth/db-checkpassword.h
--- a/src/auth/db-checkpassword.h	Sat Mar 10 13:49:12 2012 +0200
+++ b/src/auth/db-checkpassword.h	Sat Mar 10 14:11:32 2012 +0200
@@ -12,6 +12,7 @@
 
 typedef void db_checkpassword_callback_t(struct auth_request *request,
 					 enum db_checkpassword_status status,
+					 const char *const *extra_fields,
 					 void *context);
 
 struct db_checkpassword *
diff -r e3c1f3f93add -r e5ed29ef593e src/auth/passdb-checkpassword.c
--- a/src/auth/passdb-checkpassword.c	Sat Mar 10 13:49:12 2012 +0200
+++ b/src/auth/passdb-checkpassword.c	Sat Mar 10 14:11:32 2012 +0200
@@ -14,7 +14,9 @@
 
 static void
 auth_checkpassword_callback(struct auth_request *request,
-			    enum db_checkpassword_status status, void *context)
+			    enum db_checkpassword_status status,
+			    const char *const *extra_fields,
+			    void *context)
 {
 	verify_plain_callback_t *callback = context;
 
@@ -26,6 +28,7 @@
 		callback(PASSDB_RESULT_PASSWORD_MISMATCH, request);
 		break;
 	case DB_CHECKPASSWORD_STATUS_OK:
+		auth_request_set_fields(request, extra_fields, NULL);
 		callback(PASSDB_RESULT_OK, request);
 		break;
 	}
diff -r e3c1f3f93add -r e5ed29ef593e src/auth/userdb-checkpassword.c
--- a/src/auth/userdb-checkpassword.c	Sat Mar 10 13:49:12 2012 +0200
+++ b/src/auth/userdb-checkpassword.c	Sat Mar 10 14:11:32 2012 +0200
@@ -15,9 +15,11 @@
 static void
 userdb_checkpassword_callback(struct auth_request *request,
 			      enum db_checkpassword_status status,
+			      const char *const *extra_fields,
 			      void *context)
 {
 	userdb_callback_t *callback = context;
+	unsigned int i;
 
 	switch (status) {
 	case DB_CHECKPASSWORD_STATUS_INTERNAL_FAILURE:
@@ -27,6 +29,12 @@
 		callback(USERDB_RESULT_USER_UNKNOWN, request);
 		break;
 	case DB_CHECKPASSWORD_STATUS_OK:
+		for (i = 0; extra_fields[i] != NULL; i++) {
+			if (strncmp(extra_fields[i], "userdb_", 7) != 0)
+				continue;
+			auth_request_set_field_keyvalue(request,
+							extra_fields[i], NULL);
+		}
 		callback(USERDB_RESULT_OK, request);
 		break;
 	}


More information about the dovecot-cvs mailing list