Chroot patch (v3.4p1)
John Furman
john at furman.net
Sat Jul 13 10:49:13 EST 2002
To: openssh-unix-dev at mindrot.org
Subject: Re: Chroot patch (v3.4p1)
On 4 Jul 2002 12:32:36 -0400 Hank Leininger <openssh-unix-dev at progressive-comp.com> wrote:
>> The following is a patch I've been working on to support a "ChrootUser"
>> option in the sshd_config file.
[snip]
>Note that this like every(?) other chroot patch for openssh floating around
>(including the one I maintain) does not work on *BSD, that is, any system
>which has HAVE_LOGIN_CAP defined. All the chroot patches chroot between
[snip]
>fix. I'm not sure if moving the chroot calls above the block in question,
>or simply replicating the chroot code inside both code paths is
>appropriate.
>--
>Hank Leininger <hlein at progressive-comp.com>
Your supposition is correct, Hank. I have moved the 'chroot' code above the HAVE_LOGIN_CAP/setusercontext call and corrected the issue you mention. (Took some doin' as I had to free up an OpenBSD 3.x box to test on. ;-) I have created a patch for OpenSSH-v3.4 that I will post as well. Below is a patch for v3.4p1.
It supports two additional options in the sshd_config.
ChrootDir - Configured as with AuthorizedKeysFile %T tokens etc...
Defaults to a subdir named 'chome' relative to users home dir.
ChrootUser - Configured as with AllowUsers.
user1 user2 at 10.10.2.20 user3 at some.host.com
----------------------------------------------
diff -uNr openssh-3.4p1.vanilla/auth.c openssh-3.4p1/auth.c
--- openssh-3.4p1.vanilla/auth.c Wed May 22 01:06:28 2002
+++ openssh-3.4p1/auth.c Wed Jul 10 23:48:11 2002
@@ -351,6 +351,12 @@
return expand_filename(options.authorized_keys_file2, pw);
}
+char *
+chroot_dir(struct passwd *pw)
+{
+ return expand_filename(options.chroot_dir, pw);
+}
+
/* return ok if key exists in sysfile or userfile */
HostStatus
check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
diff -uNr openssh-3.4p1.vanilla/auth.h openssh-3.4p1/auth.h
--- openssh-3.4p1.vanilla/auth.h Thu Jun 6 16:52:37 2002
+++ openssh-3.4p1/auth.h Wed Jul 10 23:48:11 2002
@@ -165,6 +165,7 @@
char *expand_filename(const char *, struct passwd *);
char *authorized_keys_file(struct passwd *);
char *authorized_keys_file2(struct passwd *);
+char *chroot_dir(struct passwd *);
int
secure_filename(FILE *, const char *, struct passwd *, char *, size_t);
diff -uNr openssh-3.4p1.vanilla/pathnames.h openssh-3.4p1/pathnames.h
--- openssh-3.4p1.vanilla/pathnames.h Thu Jun 6 15:57:34 2002
+++ openssh-3.4p1/pathnames.h Wed Jul 10 23:48:11 2002
@@ -97,6 +97,9 @@
/* backward compat for protocol v2 */
#define _PATH_SSH_USER_PERMITTED_KEYS2 ".ssh/authorized_keys2"
+/* default user chroot directory */
+#define _SSH_USER_CHROOT_DIR "chome"
+
/*
* Per-user and system-wide ssh "rc" files. These files are executed with
* /bin/sh before starting the shell or command if they exist. They will be
diff -uNr openssh-3.4p1.vanilla/servconf.c openssh-3.4p1/servconf.c
--- openssh-3.4p1.vanilla/servconf.c Mon Jun 24 23:22:04 2002
+++ openssh-3.4p1/servconf.c Wed Jul 10 23:48:11 2002
@@ -120,6 +120,7 @@
options->verify_reverse_mapping = -1;
options->client_alive_interval = -1;
options->client_alive_count_max = -1;
+ options->chroot_dir = NULL;
options->authorized_keys_file = NULL;
options->authorized_keys_file2 = NULL;
@@ -252,6 +253,8 @@
}
if (options->authorized_keys_file == NULL)
options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
+ if (options->chroot_dir == NULL)
+ options->chroot_dir = _SSH_USER_CHROOT_DIR;
/* Turn privilege separation on by default */
if (use_privsep == -1)
@@ -292,12 +295,12 @@
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
sStrictModes, sEmptyPasswd, sKeepAlives,
sUseLogin, sAllowTcpForwarding, sCompression,
- sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
+ sAllowUsers, sDenyUsers, sChrootUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
- sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
+ sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, sChrootDir,
sUsePrivilegeSeparation,
sDeprecated
} ServerOpCodes;
@@ -360,6 +363,7 @@
{ "allowtcpforwarding", sAllowTcpForwarding },
{ "allowusers", sAllowUsers },
{ "denyusers", sDenyUsers },
+ { "chrootusers", sChrootUsers },
{ "allowgroups", sAllowGroups },
{ "denygroups", sDenyGroups },
{ "ciphers", sCiphers },
@@ -375,6 +379,7 @@
{ "clientalivecountmax", sClientAliveCountMax },
{ "authorizedkeysfile", sAuthorizedKeysFile },
{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
+ { "chrootdir", sChrootDir },
{ "useprivilegeseparation", sUsePrivilegeSeparation},
{ NULL, sBadOption }
};
@@ -779,6 +784,16 @@
}
break;
+ case sChrootUsers:
+ while ((arg = strdelim(&cp)) && *arg != '\0') {
+ if (options->num_chroot_users >= MAX_CHROOT_USERS)
+ fatal( "%s line %d: too many chroot users.",
+ filename, linenum);
+ options->chroot_users[options->num_chroot_users++] =
+ xstrdup(arg);
+ }
+ break;
+
case sAllowGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
@@ -893,6 +908,10 @@
&options->authorized_keys_file2;
goto parse_filename;
+ case sChrootDir:
+ charptr = &options->chroot_dir;
+ goto parse_filename;
+
case sClientAliveInterval:
intptr = &options->client_alive_interval;
goto parse_time;
diff -uNr openssh-3.4p1.vanilla/servconf.h openssh-3.4p1/servconf.h
--- openssh-3.4p1.vanilla/servconf.h Thu Jun 20 21:09:47 2002
+++ openssh-3.4p1/servconf.h Wed Jul 10 23:48:11 2002
@@ -20,6 +20,7 @@
#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */
#define MAX_DENY_USERS 256 /* Max # users on deny list. */
+#define MAX_CHROOT_USERS 256 /* Max # users on chroot list. */
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
@@ -104,6 +105,8 @@
char *allow_users[MAX_ALLOW_USERS];
u_int num_deny_users;
char *deny_users[MAX_DENY_USERS];
+ u_int num_chroot_users;
+ char *chroot_users[MAX_CHROOT_USERS];
u_int num_allow_groups;
char *allow_groups[MAX_ALLOW_GROUPS];
u_int num_deny_groups;
@@ -130,6 +133,7 @@
char *authorized_keys_file; /* File containing public keys */
char *authorized_keys_file2;
+ char *chroot_dir;
int pam_authentication_via_kbd_int;
} ServerOptions;
diff -uNr openssh-3.4p1.vanilla/session.c openssh-3.4p1/session.c
--- openssh-3.4p1.vanilla/session.c Wed Jun 26 09:51:06 2002
+++ openssh-3.4p1/session.c Fri Jul 12 15:37:58 2002
@@ -57,6 +57,8 @@
#include "canohost.h"
#include "session.h"
#include "monitor_wrap.h"
+#include "match.h"
+#include "readconf.h"
#ifdef HAVE_CYGWIN
#include <windows.h>
@@ -64,6 +66,10 @@
#define is_winnt (GetVersion() < 0x80000000)
#endif
+#ifndef HAVE_CYGWIN
+#define CHROOT
+#endif
+
/* func */
Session *session_new(void);
@@ -1169,6 +1175,38 @@
#ifdef HAVE_SETPCRED
setpcred(pw->pw_name);
#endif /* HAVE_SETPCRED */
+#ifdef CHROOT
+ int i;
+ char *new_root = "/";
+ char *new_home = NULL;
+ char *dir = NULL;
+ const char *hostname = NULL;
+ const char *ipaddr = NULL;
+
+ if (options.num_chroot_users > 0) {
+ hostname = get_canonical_hostname(options.verify_reverse_mapping);
+ ipaddr = get_remote_ipaddr();
+ for (i = 0; i < options.num_chroot_users; i++) {
+ if (match_user(pw->pw_name, hostname, ipaddr,
+ options.chroot_users[i])) {
+ dir = chroot_dir(pw);
+ new_home = dir;
+ xfree(dir);
+ if(chdir(new_home) == -1)
+ fatal("chdir to %s failed: %s",
+ new_home, strerror(errno));
+ if(chroot(new_home) == -1) {
+ fatal("chroot to %s failed: %s",
+ new_home, strerror(errno));
+ }
+ else
+ pw->pw_dir = new_root;
+ }
+ }
+ }
+
+
+#endif /* CHROOT */
#ifdef HAVE_LOGIN_CAP
#ifdef __bsdi__
setpgid(0, 0);
--------------------------------
Regards,
--
John Furman <john at furna.net>
More information about the openssh-unix-dev
mailing list