From: Timo Sirainen Date: Thu, 8 May 2003 04:28:30 +0000 (+0300) Subject: Chrooting changes. Now all userdbs will support "/./" style X-Git-Tag: 1.1.alpha1~4663 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=061da1b9d309301a7e3f5e0f240d7a7e99652d63;p=thirdparty%2Fdovecot%2Fcore.git Chrooting changes. Now all userdbs will support "/./" style home directories. --HG-- branch : HEAD --- diff --git a/doc/auth.txt b/doc/auth.txt index 79e02b0eb5..d790c8bc66 100644 --- a/doc/auth.txt +++ b/doc/auth.txt @@ -53,6 +53,10 @@ Realms (or virtual domains) are supported by appending the "@realm" after the user name. This behaviour works with all authentication mechanisms and databases. +Home directory can be prefixed with "/./" in which case +directory will be chrooted into. The actual home directory follows the +"/./". For example "/chroot/./home/user". + passwd ------ @@ -62,7 +66,6 @@ nowadays so it doesn't usually work as password database. BSDs are an exception to this, they still set the password field even with shadow passwords. -As an extension, if home directory ends with "/./", it will be chrooted to. shadow ------ diff --git a/doc/dovecot-ldap.conf b/doc/dovecot-ldap.conf index 25ec89d773..f901a590dd 100644 --- a/doc/dovecot-ldap.conf +++ b/doc/dovecot-ldap.conf @@ -37,7 +37,6 @@ base = uid=someone, dc=foo, dc=bar, dc=org # System user name (for initgroups()) # System UID # System GID -# Chroot to home directory? (yes / no) #user_attrs = uid,homeDirectory,,uid,uidNumber,gidNumber # Filter for user lookup. Some variables can be used: diff --git a/doc/dovecot-pgsql.conf b/doc/dovecot-pgsql.conf index b43cfdb0a6..f37e321355 100644 --- a/doc/dovecot-pgsql.conf +++ b/doc/dovecot-pgsql.conf @@ -61,7 +61,6 @@ # system_user - System user name (for initgroups()) # uid - System UID # gid - System GID -# chroot - Chroot to home directory? (Y / N) # # Either home or mail is required. uid and gid are required. If more than one # row is returned or there's missing fields, login will automatically fail. diff --git a/src/auth/auth-master-interface.h b/src/auth/auth-master-interface.h index fe89a8b7e3..1494bb7373 100644 --- a/src/auth/auth-master-interface.h +++ b/src/auth/auth-master-interface.h @@ -14,7 +14,6 @@ struct auth_master_reply { unsigned int tag; unsigned int success:1; - unsigned int chroot:1; /* chroot to home directory */ uid_t uid; gid_t gid; @@ -24,7 +23,7 @@ struct auth_master_reply { Ignore if it points outside data_size. */ size_t system_user_idx; size_t virtual_user_idx; - size_t home_idx, mail_idx; + size_t home_idx, mail_idx, chroot_idx; size_t data_size; /* unsigned char data[]; */ diff --git a/src/auth/db-passwd-file.c b/src/auth/db-passwd-file.c index 1d740a2f6f..73356b6adb 100644 --- a/src/auth/db-passwd-file.c +++ b/src/auth/db-passwd-file.c @@ -100,8 +100,7 @@ static void passwd_file_add(struct passwd_file *pw, const char *username, /* flags */ if (*args != NULL) { - if (strstr(*args, "chroot") != NULL) - pu->chroot = TRUE; + /* no flags currently */ args++; } diff --git a/src/auth/db-passwd-file.h b/src/auth/db-passwd-file.h index 40398ecb93..1ba31e1394 100644 --- a/src/auth/db-passwd-file.h +++ b/src/auth/db-passwd-file.h @@ -12,8 +12,6 @@ struct passwd_user { char *mail; char *password; - - unsigned int chroot:1; }; struct passwd_file { diff --git a/src/auth/master-connection.c b/src/auth/master-connection.c index 4fa1476c18..4e4be63a7f 100644 --- a/src/auth/master-connection.c +++ b/src/auth/master-connection.c @@ -39,6 +39,7 @@ fill_reply(const struct user_data *user, size_t *reply_size) { struct auth_master_reply *reply; buffer_t *buf; + char *p; buf = buffer_create_dynamic(data_stack_pool, sizeof(*reply) + 256, (size_t)-1); @@ -46,15 +47,23 @@ fill_reply(const struct user_data *user, size_t *reply_size) reply->success = TRUE; - reply->chroot = user->chroot; reply->uid = user->uid; reply->gid = user->gid; reply->system_user_idx = reply_add(buf, user->system_user); reply->virtual_user_idx = reply_add(buf, user->virtual_user); - reply->home_idx = reply_add(buf, user->home); reply->mail_idx = reply_add(buf, user->mail); + p = strstr(user->home, "/./"); + if (p == NULL) { + reply->home_idx = reply_add(buf, user->home); + reply->chroot_idx = reply_add(buf, NULL); + } else { + /* wu-ftpd like /./ */ + reply->home_idx = reply_add(buf, t_strdup_until(user->home, p)); + reply->chroot_idx = reply_add(buf, p + 3); + } + *reply_size = buffer_get_used_size(buf); reply->data_size = *reply_size - sizeof(*reply); return reply; diff --git a/src/auth/userdb-ldap.c b/src/auth/userdb-ldap.c index a6a5ef0d73..37647e06cd 100644 --- a/src/auth/userdb-ldap.c +++ b/src/auth/userdb-ldap.c @@ -24,7 +24,6 @@ enum ldap_user_attr { ATTR_SYSTEM_USER, ATTR_UID_NUMBER, ATTR_GID_NUMBER, - ATTR_CHROOT, ATTR_COUNT }; @@ -78,9 +77,6 @@ static void parse_attr(struct userdb_ldap_connection *conn, case ATTR_GID_NUMBER: user->gid = atoi(value); break; - case ATTR_CHROOT: - user->chroot = value[0] == 'Y' || value[0] == 'y'; - break; case ATTR_COUNT: break; diff --git a/src/auth/userdb-passwd-file.c b/src/auth/userdb-passwd-file.c index a7e8bd6b8c..9fd1456a37 100644 --- a/src/auth/userdb-passwd-file.c +++ b/src/auth/userdb-passwd-file.c @@ -31,8 +31,6 @@ static void passwd_file_lookup(const char *user, userdb_callback_t *callback, data.home = pu->home; data.mail = pu->mail; - data.chroot = pu->chroot; - callback(&data, context); } diff --git a/src/auth/userdb-passwd.c b/src/auth/userdb-passwd.c index f1f5de762d..601463d202 100644 --- a/src/auth/userdb-passwd.c +++ b/src/auth/userdb-passwd.c @@ -15,7 +15,6 @@ static void passwd_lookup(const char *user, userdb_callback_t *callback, { struct user_data data; struct passwd *pw; - size_t len; pw = getpwnam(user); if (pw == NULL) { @@ -32,16 +31,7 @@ static void passwd_lookup(const char *user, userdb_callback_t *callback, data.gid = pw->pw_gid; data.virtual_user = data.system_user = pw->pw_name; - - len = strlen(pw->pw_dir); - if (len < 3 || strcmp(pw->pw_dir + len - 3, "/./") != 0) - data.home = pw->pw_dir; - else { - /* wu-ftpd uses /./. We don't support - the dir after chroot, but this should work well enough. */ - data.home = t_strndup(pw->pw_dir, len-3); - data.chroot = TRUE; - } + data.home = pw->pw_dir; callback(&data, context); } diff --git a/src/auth/userdb-pgsql.c b/src/auth/userdb-pgsql.c index 716fd70027..be80cf8df0 100644 --- a/src/auth/userdb-pgsql.c +++ b/src/auth/userdb-pgsql.c @@ -69,7 +69,6 @@ static void pgsql_handle_request(struct pgsql_connection *conn __attr_unused__, struct userdb_pgsql_request *urequest = (struct userdb_pgsql_request *) request; struct user_data user; - const char *str; if (res != NULL && is_result_valid(res)) { memset(&user, 0, sizeof(user)); @@ -79,8 +78,6 @@ static void pgsql_handle_request(struct pgsql_connection *conn __attr_unused__, user.mail = pg_get_str(res, "mail"); user.uid = atoi(PQgetvalue(res, 0, PQfnumber(res, "uid"))); user.gid = atoi(PQgetvalue(res, 0, PQfnumber(res, "gid"))); - str = pg_get_str(res, "chroot"); - user.chroot = str != NULL && (*str == 'Y' || *str == 'y'); urequest->userdb_callback(&user, request->context); } else { urequest->userdb_callback(NULL, request->context); diff --git a/src/auth/userdb.h b/src/auth/userdb.h index 9553c7d096..75a5527bbe 100644 --- a/src/auth/userdb.h +++ b/src/auth/userdb.h @@ -9,8 +9,6 @@ struct user_data { const char *system_user; uid_t uid; gid_t gid; - - int chroot; /* chroot to home directory */ }; typedef void userdb_callback_t(struct user_data *user, void *context); diff --git a/src/master/auth-process.c b/src/master/auth-process.c index ce19d22095..9a67d37571 100644 --- a/src/master/auth-process.c +++ b/src/master/auth-process.c @@ -90,6 +90,8 @@ static int handle_reply(struct auth_process *process, reply->virtual_user_idx = nul_pos; if (reply->home_idx >= reply->data_size) reply->home_idx = nul_pos; + if (reply->chroot_idx >= reply->data_size) + reply->chroot_idx = nul_pos; if (reply->mail_idx >= reply->data_size) reply->mail_idx = nul_pos; diff --git a/src/master/mail-process.c b/src/master/mail-process.c index 26b94cf1f7..9fde9b7343 100644 --- a/src/master/mail-process.c +++ b/src/master/mail-process.c @@ -105,7 +105,7 @@ int create_mail_process(int socket, struct ip_addr *ip, const char *data) { static const char *argv[] = { NULL, NULL, NULL }; - const char *host, *mail, *home_dir; + const char *host, *mail, *chroot_dir, *home_dir, *full_home_dir; char title[1024]; pid_t pid; int i, err; @@ -118,8 +118,11 @@ int create_mail_process(int socket, struct ip_addr *ip, if (!validate_uid_gid(reply->uid, reply->gid)) return FALSE; - if (reply->chroot && !validate_chroot(data + reply->home_idx)) { - i_error("Invalid chroot directory: %s", data + reply->home_idx); + home_dir = data + reply->home_idx; + chroot_dir = data + reply->chroot_idx; + + if (*chroot_dir != '\0' && validate_chroot(chroot_dir)) { + i_error("Invalid chroot directory: %s", chroot_dir); return FALSE; } @@ -151,15 +154,15 @@ int create_mail_process(int socket, struct ip_addr *ip, /* setup environment - set the most important environment first (paranoia about filling up environment without noticing) */ restrict_access_set_env(data + reply->system_user_idx, - reply->uid, reply->gid, - reply->chroot ? data + reply->home_idx : NULL); + reply->uid, reply->gid, chroot_dir); restrict_process_size(process_size, (unsigned int)-1); - home_dir = data + reply->home_idx; if (*home_dir != '\0') { - if (chdir(home_dir) < 0) - i_fatal("chdir(%s) failed: %m", home_dir); + full_home_dir = *chroot_dir == '\0' ? home_dir : + t_strconcat(chroot_dir, "/", home_dir, NULL); + if (chdir(full_home_dir) < 0) + i_fatal("chdir(%s) failed: %m", full_home_dir); } env_put("LOGGED_IN=1"); @@ -204,7 +207,7 @@ int create_mail_process(int socket, struct ip_addr *ip, if (*mail == '\0' && set->default_mail_env != NULL) { mail = expand_mail_env(set->default_mail_env, data + reply->virtual_user_idx, - data + reply->home_idx); + home_dir); } env_put(t_strconcat("MAIL=", mail, NULL));