dovecot-1.3: Fixed problems with getting home directory.

dovecot at dovecot.org dovecot at dovecot.org
Fri Apr 10 20:38:48 EEST 2009


details:   http://hg.dovecot.org/dovecot-1.3/rev/daa079a90b66
changeset: 9063:daa079a90b66
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Apr 10 13:38:43 2009 -0400
description:
Fixed problems with getting home directory.

diffstat:

1 file changed, 81 insertions(+), 23 deletions(-)
src/lib-storage/mail-storage-service.c |  104 ++++++++++++++++++++++++--------

diffs (202 lines):

diff -r 0b8009b5aff8 -r daa079a90b66 src/lib-storage/mail-storage-service.c
--- a/src/lib-storage/mail-storage-service.c	Fri Apr 10 13:16:44 2009 -0400
+++ b/src/lib-storage/mail-storage-service.c	Fri Apr 10 13:38:43 2009 -0400
@@ -2,9 +2,12 @@
 
 #include "lib.h"
 #include "array.h"
-#include "dict.h"
+#include "hostpid.h"
 #include "module-dir.h"
 #include "restrict-access.h"
+#include "str.h"
+#include "var-expand.h"
+#include "dict.h"
 #include "settings-parser.h"
 #include "auth-master.h"
 #include "master-service-private.h"
@@ -206,7 +209,7 @@ static bool parse_gid(const char *str, g
 
 static void
 service_drop_privileges(const struct mail_user_settings *set,
-			const char *system_groups_user,
+			const char *system_groups_user, const char *home,
 			bool disallow_root, bool keep_setuid_root)
 {
 	struct restrict_access_settings rset;
@@ -264,8 +267,7 @@ service_drop_privileges(const struct mai
 		setuid_uid = rset.uid;
 		rset.uid = (uid_t)-1;
 	}
-	restrict_access(&rset, *set->mail_home == '\0' ? NULL : set->mail_home,
-			disallow_root);
+	restrict_access(&rset, *home == '\0' ? NULL : home, disallow_root);
 	if (keep_setuid_root) {
 		if (seteuid(setuid_uid) < 0)
 			i_fatal("seteuid(%s) failed: %m", dec2str(setuid_uid));
@@ -299,20 +301,25 @@ mail_storage_service_init_settings(struc
 }
 
 static int
-mail_storage_service_init_post(struct master_service *service, const char *user,
+mail_storage_service_init_post(struct master_service *service,
+			       const char *user, const char *home,
 			       const struct mail_user_settings *user_set,
 			       struct mail_user **mail_user_r,
 			       const char **error_r)
 {
 	const struct mail_storage_settings *mail_set;
 	struct mail_user *mail_user;
-	const char *home;
 
 	mail_set = mail_user_set_get_storage_set(user_set);
+
+	if (mail_set->mail_debug) {
+		i_info("Effective uid=%s, gid=%s, home=%s",
+		       dec2str(geteuid()), dec2str(getegid()),
+		       home != NULL ? home : "(none)");
+	}
 
 	/* If possible chdir to home directory, so that core file
 	   could be written in case we crash. */
-	home = user_set->mail_home;
 	if (*home != '\0') {
 		if (chdir(home) < 0) {
 			if (errno != ENOENT)
@@ -336,6 +343,49 @@ mail_storage_service_init_post(struct ma
 	return 0;
 }
 
+static const struct var_expand_table *
+get_var_expand_table(struct master_service *service, const char *user)
+{
+	static struct var_expand_table static_tab[] = {
+		{ 'u', NULL, "user" },
+		{ 'n', NULL, "username" },
+		{ 'd', NULL, "domain" },
+		{ 's', NULL, "service" },
+		{ 'p', NULL, "pid" },
+		{ 'i', NULL, "uid" },
+		{ '\0', NULL, NULL }
+	};
+	struct var_expand_table *tab;
+
+	tab = t_malloc(sizeof(static_tab));
+	memcpy(tab, static_tab, sizeof(static_tab));
+
+	tab[0].value = user;
+	tab[1].value = t_strcut(user, '@');
+	tab[2].value = strchr(user, '@');
+	if (tab[2].value != NULL) tab[2].value++;
+	tab[3].value = service->name;
+	tab[4].value = my_pid;
+	tab[5].value = dec2str(geteuid());
+	return tab;
+}
+
+static const char *
+user_expand_varstr(struct master_service *service, const char *user,
+		   const char *str)
+{
+	string_t *ret;
+
+	if (*str == SETTING_STRVAR_EXPANDED[0])
+		return str + 1;
+
+	i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
+
+	ret = t_str_new(256);
+	var_expand(ret, str + 1, get_var_expand_table(service, user));
+	return str_c(ret);
+}
+
 struct mail_user *
 mail_storage_service_init_user(struct master_service *service, const char *user,
 			       const struct setting_parser_info *set_root,
@@ -372,16 +422,21 @@ mail_storage_service_init_user(struct ma
 		if (service_auth_userdb_lookup(service, mail_set->mail_debug,
 					       user_set, &user,
 					       &system_groups_user,
-					       &error) <= 0) {
+					       &error) <= 0)
 			i_fatal("%s", error);
-		}
-	} else {
-		home = getenv("HOME");
+	}
+
+	/* variable strings are expanded in mail_user_init(),
+	   but we need the home sooner so do it separately here. */
+	home = user_expand_varstr(service, user, user_set->mail_home);
+
+	if (!userdb_lookup) {
 		system_groups_user = NULL;
-		if (*user_set->mail_home == '\0' && home != NULL)
+		if (*home == '\0' && getenv("HOME") != NULL) {
+			home = getenv("HOME");
 			master_service_set(service, "mail_home", home);
-	}
-	home = user_set->mail_home;
+		}
+	}
 
 	len = strlen(user_set->mail_chroot);
 	if (len > 2 && strcmp(user_set->mail_chroot + len - 2, "/.") == 0 &&
@@ -396,14 +451,14 @@ mail_storage_service_init_user(struct ma
 				user_set->mail_plugins, TRUE,
 				master_service_get_version_string(service));
 
-	service_drop_privileges(user_set, system_groups_user,
+	service_drop_privileges(user_set, system_groups_user, home,
 		(flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0, FALSE);
 	/* privileges are now dropped */
 
 	dict_drivers_register_builtin();
 	module_dir_init(modules);
 	mail_users_init(user_set->auth_socket_path, mail_set->mail_debug);
-	if (mail_storage_service_init_post(service, user, user_set,
+	if (mail_storage_service_init_post(service, user, home, user_set,
 					   &mail_user, &error) < 0)
 		i_fatal("%s", error);
 	return mail_user;
@@ -461,7 +516,7 @@ int mail_storage_service_multi_next(stru
 {
 	const struct mail_user_settings *user_set;
 	const struct mail_storage_settings *mail_set;
-	const char *orig_user, *system_groups_user;
+	const char *orig_user, *system_groups_user, *home;
 	void **sets;
 	unsigned int len;
 	int ret;
@@ -483,7 +538,11 @@ int mail_storage_service_multi_next(stru
 		system_groups_user = NULL;
 	}
 
-	service_drop_privileges(user_set, system_groups_user,
+	/* variable strings are expanded in mail_user_init(),
+	   but we need the home sooner so do it separately here. */
+	home = user_expand_varstr(ctx->service, user, user_set->mail_home);
+
+	service_drop_privileges(user_set, system_groups_user, home,
 		(ctx->flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0, TRUE);
 
 	if (!ctx->modules_initialized) {
@@ -497,14 +556,13 @@ int mail_storage_service_multi_next(stru
 	   the home directory */
 	len = strlen(user_set->mail_chroot);
 	if (len > 2 && strcmp(user_set->mail_chroot + len - 2, "/.") == 0 &&
-	    strncmp(user_set->mail_home, user_set->mail_chroot, len - 2) == 0) {
+	    strncmp(home, user_set->mail_chroot, len - 2) == 0) {
 		/* home dir already contains the chroot dir */
 	} else if (len > 0) {
 		master_service_set(ctx->service, "mail_home",
-				   t_strconcat(user_set->mail_chroot, "/",
-					       user_set->mail_home, NULL));
-	}
-	if (mail_storage_service_init_post(ctx->service, user,
+			t_strconcat(user_set->mail_chroot, "/", home, NULL));
+	}
+	if (mail_storage_service_init_post(ctx->service, user, home,
 					   user_set, mail_user_r, error_r) < 0)
 		return -1;
 	return 1;


More information about the dovecot-cvs mailing list