dovecot-2.0: lmtp: Fixes to seteuid calls.

dovecot at dovecot.org dovecot at dovecot.org
Mon May 31 23:38:52 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/55b8480849b0
changeset: 11439:55b8480849b0
user:      Timo Sirainen <tss at iki.fi>
date:      Mon May 31 21:38:19 2010 +0100
description:
lmtp: Fixes to seteuid calls.
When delivering to multiple users, the first user's mail should be
deinitialized with that user's effective uid. Also there's no point in
setting uid to 0 between deliveries to multiple users.

diffstat:

 src/lmtp/commands.c |  31 +++++++++++++++++++++----------
 1 files changed, 21 insertions(+), 10 deletions(-)

diffs (82 lines):

diff -r 7adc45a6da2e -r 55b8480849b0 src/lmtp/commands.c
--- a/src/lmtp/commands.c	Mon May 31 20:34:42 2010 +0100
+++ b/src/lmtp/commands.c	Mon May 31 21:38:19 2010 +0100
@@ -415,13 +415,10 @@
 	struct mail_storage *storage;
 	const struct mail_storage_service_input *input;
 	void **sets;
-	uid_t old_uid;
 	const char *error, *username;
 	enum mail_error mail_error;
 	int ret;
 
-	old_uid = geteuid();
-
 	input = mail_storage_service_user_get_input(rcpt->service_user);
 	username = t_strdup(input->username);
 
@@ -474,13 +471,6 @@
 		}
 		ret = -1;
 	}
-	if (old_uid == 0) {
-		/* switch back to running as root, since that's what we're
-		   practically doing anyway. it's also important in case we
-		   lose e.g. config connection and need to reconnect to it. */
-		if (seteuid(0) < 0)
-			i_fatal("seteuid(0) failed: %m");
-	}
 	pool_unref(&dctx.pool);
 	return ret;
 }
@@ -584,10 +574,12 @@
 client_input_data_write_local(struct client *client, struct istream *input)
 {
 	struct mail *src_mail;
+	uid_t old_uid, first_uid;
 
 	if (client_open_raw_mail(client, input) < 0)
 		return;
 
+	old_uid = geteuid();
 	src_mail = client->state.raw_mail;
 	while (client_deliver_next(client, src_mail)) {
 		if (client->state.first_saved_mail == NULL ||
@@ -598,6 +590,8 @@
 			   this might allow hard linking the files. */
 			client->state.dest_user = NULL;
 			src_mail = client->state.first_saved_mail;
+			first_uid = geteuid();
+			i_assert(first_uid != 0);
 		}
 	}
 
@@ -607,11 +601,28 @@
 		struct mailbox *box = trans->box;
 		struct mail_user *user = box->storage->user;
 
+		/* just in case these functions are going to write anything,
+		   change uid back to user's own one */
+		if (first_uid != old_uid) {
+			if (seteuid(0) < 0)
+				i_fatal("seteuid(0) failed: %m");
+			if (seteuid(first_uid) < 0)
+				i_fatal("seteuid() failed: %m");
+		}
+
 		mail_free(&mail);
 		mailbox_transaction_rollback(&trans);
 		mailbox_free(&box);
 		mail_user_unref(&user);
 	}
+
+	if (old_uid == 0) {
+		/* switch back to running as root, since that's what we're
+		   practically doing anyway. it's also important in case we
+		   lose e.g. config connection and need to reconnect to it. */
+		if (seteuid(0) < 0)
+			i_fatal("seteuid(0) failed: %m");
+	}
 }
 
 static void client_input_data_finish(struct client *client)


More information about the dovecot-cvs mailing list